MICHAEL ONTIVEROS

There are some existing typos in the tables in addition to those produced during the use of Magick. I made some assumptions along the way, documenting them. These need to be checked for accuracy.

Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 (CC BY-NC 3.0) United States License.

To cite this case study please use:

Wright, Carrie, and Ontiveros, Michael and Jager, Leah and Taub, Margaret and Hicks, Stephanie. (2020). https://github.com/opencasestudies/ocs-youth-disconnection-case-study. Disparities in Youth Disconnection (Version v1.0.0).

Motivation


According to this report youth disconnection although generally showing decreasing trends for the past 7 years, shows racial and ethnic disparities, where some groups are showing increased rates of disconnection.

So what does the term “youth disconnection” mean?

According to Measure of America (a nonpartisan project of the nonprofit Social Science Research Council that is focused on opportunity in the United States) disconnected youth are:

“young people between the ages of 16 and 24 who are neither working nor in school

They state that such disconnection hinders these individuals to aquire skills and create relationships necessary to have a sucessful adulthood.

They state that:

“people who experience a period of disconnection as young adults go on to earn less and are less likely to be employed, own a home, or report good health by the time they reach their thirties”

Disconnected youth are also referred to as opportunity youth, which has the added positive connotation that promoting such individuals can be beneficial not only for these individuals but also for their communties and for society.

We will expand beyond the Measure of America annual report to take a deeper look at differences of specific groups of youths. Identifying youths particularly at risk or disconnected, can help inform the design of targeted prevention and rengagement strategies.

This case study is motivated by this article:

Mendelson, T., Mmari, K., Blum, R. W., Catalano, R. F. & Brindis, C. D. Opportunity Youth: Insights and Opportunities for a Public Health Approach to Reengage Disconnected Teenagers and Young Adults. Public Health Rep 133, 54S-64S (2018).

This article describes strategies for prevention of disconnection and reengagement of discconnected youth and how such interventions could greatly positively impact opportunity youth for the entire trajectory of their lives and for future generations. It also points out that indeed their are disparities among different racial/ethnic groups.

Main Questions


Our main questions:

  1. How have youth disconnection rates in American youth changed since 2008?
  2. In particular, how has this changed for different gender and ethnic groups? Are any groups particularly disconnected?

Learning Objectives


In this case study, we will demonstrate how to import and wrangle data available in the Portable Document Format (PDF). We will especially focus on using packages and functions from the Tidyverse, such as dplyr, ggplot2. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.

The skills, methods, and concepts that students will be familiar with by the end of this case study are:

Data science skills:

  1. Importing data from PDF files using the magick package
  2. Apply action verbs in dplyr for data wrangling
  3. How to pivot between “long” and “wide” datasets (tidyr)
  4. Joining together multiple datasets using dplyr
  5. How to create data visualizations with ggplot2 that are in a similar style to an existing image

Statistical concepts and methods:

  1. Implementation of the Mann-Kendall trend test
  2. Interpretation of the Mann-Kendall trend test


We will begin by loading the packages that we will need:

Package Use
here to easily load and save data
tidyverse for data science operations
pdftools to manage PDF documents
magick for image processing

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

Context


So how does youth disconnection happen and what impact does it have?

There are many known risk factors, which have been identified in a variety of contexts (from family, friends, school, community, society) including:

  • poverty (disconnected youth are nearly twice as likely to live in poverty and receive Medicaid)
  • racial/ethnic disparities (findings suggest that these persist even when controlling for income)
  • residential environment (in 2016 while 11.7% was the national average, 24% of people age 16-24 in the rural South were disconnected)
  • poor academic performance
  • poor mental health
  • substance use disorders
  • parental unemployment
  • trauma exposure
  • association with socially deviant peers
  • school policies such as “one strike and you’re out” - which is a zero tolerance school expulsion policy and shown to increase dropouts and incarceration rates

These risk factors make it more likely for young people to miss out on education, training, and networking that can act as a foundation for a sucessful career.

There are also many known negative consequences associated with youth disconnection including but not limited to:

  • chronic unemployment
  • poverty
  • poor menthal health and poor general health (in a 2002 study - youths discoonected for 6 or more months were 3 times more likely to develop depression or other mental health disorder)
  • crimial behavior (in a 2002 study - youths discoonected for 6 or more months were 5 times more likely to have a criminal record)
  • incarceration
  • early mortality

Photo by Jon Tyson on Unsplash

Furthermore, in 2012 it was estimated that each disconnected youth costs taxpayers $250000 during a life time due to lost tax revenue and costs for social sercices, heath care and criminal justice.

Youth disconnection can be described as a continuum, as some youths will be disconnected for a brief time, while others are chronically disconnected. Additionally, while an individual who is out of school and work and also has poor support from the realtionships of others may be further disconnected than an individual who has social support.

Here is an illustration of risk factors, protective factors and the continuum of disconnection:

##### [source]

Strategies to mitigate youth disconnection

Many programs have identified useful strategies in rengaging disconnected youth or preventing discconection of youth.

generally speaking, most programs focus on reengagement strategies, however, prevention strategies are likely to be just as important.

Reserach suggests that active involvement with at risk youth from infancy and across multiple developmental stages through young adulthood whould be the most beneficial.

In fact, the quality of parental caregiving of infants age 6-24 months has actually been shown to be a predictor of high school dropout rates! Thus early interventions may be very important and consistent continual engagement may prevent further disconnection of youths.

Prevention strategies include:

See here and here for listings of programs dedicated to rengaging disconnected youth or preventing disconnection.

See here and here for particular examples.

The statistics used in this section came from this article.

Limitations


There are some important considerations regarding this data analysis to keep in mind:

  1. This data used in the Measure of America project reports from the is derived from American Community Survey(ASC) which excludes or underrepresents certain opportunity youth groups, such as youths in the juvenile justice system, youths in the foster care system, and homeless youths as the survey is conducted on households. Furthermore, youths who may be more disconnected for other reasons besides not being in work or school, such as dealing with the added challenge of being a teenage mother, or being abused is not available in this dataset. Thus, this data likely underestimates youth disconnection rates.

  2. Data about certain group intersections (meaning for example individuals of a particular gender and ethnicity) or particular groups in general such as specific ethnicities or gender or sexual identity groups such as LGBT (lesbian/gay/bisexual/transgender/queer and questioning) or nonbinary gender populations is unfortunately not available in the data used in this analysis and in most research about this topic. Luckily however, recent years of the ACS survey has more detailed infromation about a greater number of racial and ethnic groups and racial/ethnic intersections.

  3. The statistical procedures we are using may be overly simplistic. In all data analysis, we need to be wary about deriving meaning from the statistical procedures we use.

  4. Using image processing tools can be very helpful. The manner in which data is obtained with image processing tools is what we would describe as a black box process, a process with known inputs and outputs but unknown mechanics. Because we are unaware of how our outputs are generated from our inputs, we need to be wary of the output. With the small output we are creating in this case study, a visual inspection should suffice.

What are the data?


In this case study we will be using data related to youth disconnection from the two following reports from the Measure of America project:

Measure of America is a nonpartisan project of the nonprofit Social Science Research Council founded in 2007 to create easy-to-use yet methodologically sound tools for understanding well-being and opportunity in America. Through reports, interactive apps, and custom-built dashboards, Measure of America works with partners to breathe life into numbers, using data to identify areas of highest need, pinpoint levers for change, and track progress over time.

  1. Lewis, Kristen. Making the Connection: Transportation and Youth Disconnection . New York: Measure of America, Social Science Research Council, 2019. (Data up to 2017)

  1. : Lewis, Kristen. A Decade Undone: Youth Disconnection in the Age of Coronavirus. New York: Measure of America, Social Science Research Council, 2020. (Data up to 2018)

The data used in these reports comes from the American Community Survey(ASC), which is the largest survey conducted by the United States Census Bureau. The survey started in 2005 and collects data for 3.5 million households annually. Data is collected about ancestry, citizehsip, income, employment, disability among many other aspects. See here for more detailed information about the survey.

According to Wikipedia (https://en.wikipedia.org/wiki/American_Community_Survey){target="_blank"}:

Data is collected by internet, mail, telephone interviews and in-person interviews…About 95 percent of households across all response modes ultimately respond… ACS responses are confidential… and “immune from legal process”

It is a mandatory survey, it is governed by federal laws that could impose a fine of as much as $5,000 for refusing to participate.

Data Import


One way to import data from a pdf is to use the pdftools packages.

From the output, it’s clear that a large amount of manipulation will be required to wrangle this data with the pdftools package.

[[1]]
# A tibble: 51 x 6
   width height     x     y space text    
   <int>  <int> <int> <int> <lgl> <chr>   
 1    74     23    36    53 TRUE  KRISTEN 
 2    54     23   115    53 FALSE LEWIS   
 3    31     11    36    79 TRUE  Rupsha  
 4    20     11    69    79 TRUE  Basu    
 5     2     11    94    79 TRUE  |       
 6    34     11   101    79 TRUE  REPORT  
 7    43     11   138    79 FALSE DESIGNER
 8    34     11    36    92 TRUE  Rebecca 
 9    31     11    73    92 TRUE  Gluskin 
10     2     11   109    92 TRUE  |       
# … with 41 more rows
[1] "KRISTEN LEWIS\nRupsha Basu | REPORT DESIGNER\nRebecca Gluskin | CHIEF STATISTICIAN\nLaura Laderman | DATA ANALYST\nVikki Lassiter | STAKEHOLDER ENGAGEMENT\nBecky Ofrane | RESEARCHER\nBeth Post | REPORT DESIGNER\nMarina Recio | RESEARCHER\nMAKING THE CONNECTION\nTRANSPORTATION AND YOUTH DISCONNECTION\n                                        MEA SUREOF AMERICA\n                                        of the Social Science Research Council\n"

While not impossible, it’s hard not to argue that using the pdftools package in this scenario will require a lot of advanced data wrangling. While our output may be reproducible, the amount of time to achieve this reproducibility may not be any more efficient than typing the table by hand into a text or spreadsheet program.

Fortunately, there is another way we can proceed to wrangle the data.

We will demonstrate how to produce reproducible tables with image processing software in R.

For demonstrative purposes, we will import two sets of data. The first set of data will be used to highlight common errors that the image processing software may produce. The second set of data will be used to demonstrate how to circumvent these errors and produce reproducible datasets efficiently.

We will now import the data using the magick and here packages.

# A tibble: 1 x 7
  format width height colorspace matte filesize density
  <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
1 PNG      997    711 sRGB       TRUE    164964 72x72  

We import the same data—this time without regions of the table without special formatting—using the magick and here packages.

# A tibble: 1 x 7
  format width height colorspace matte filesize density
  <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
1 PNG     1259    731 sRGB       TRUE    188256 72x72  

Data Exploration and Wrangling


The first image we imported looks like this.

Parts of the table depicted in the image above contain newline characters. A newline character denotes the end of a line of text and the start of a new line of text.

This makes it more difficult to wrangle this table. Wrangling the data via regular expressions may be very tedious. It’s unlikely that image processing software can handle the newline characters—or any other special characters—correctly.

Using image_ocr() by magick on the image above will render some errors in the first few lines.

# A tibble: 21 x 1
   value                                                  
   <chr>                                                  
 1 Youth Disconnection by Gender and by Race and Ethnicity
 2 byte) ee                                               
 3 MAJOR RACIAL AND Cr erent) ed Nas                      
 4 United States 126 147 14.1 13.21.7115 4,501,800 22.1   
 5 Male 12.3 15.2 14.5 13.3 12.1 11.8 2,382,500 -22.5     
 6 Female 12.9 14.1 13.7 13.0 11.2 11.1 2,119,400 -21.7   
 7 ASIAN 71 85 78 19 66 66 145,600 -21.7                  
 8 Asian Male 6.3 8.3 74 7.2 6.7 65 73,000 -21.4          
 9 Asian Female 7.9 8.6 8.1 8.6 6.6 6.7 72,600 -22.0      
10 WHITE 97 210897 9.4 1,961,700 -20.1                    
# … with 11 more rows

If we remove these lines, some new errors emerge.

# A tibble: 18 x 1
   value                                                           
   <chr>                                                           
 1 United States 126 147 14.1 13.21.7115 4,501,800 22.1            
 2 Male 12.3 15.2 14.5 13.3 12.1 11.8 2,382,500 -22.5              
 3 Female 12.9 14.1 13.7 13.0 11.2 11.1 2,119,400 -21.7            
 4 ASIAN 71 85 78 19 66 66 145,600 -21.7                           
 5 Asian Male 6.3 8.3 74 7.2 6.7 65 73,000 -21.4                   
 6 Asian Female 7.9 8.6 8.1 8.6 6.6 6.7 72,600 -22.0               
 7 WHITE 97 210897 9.4 1,961,700 -20.1                             
 8 White Male 95 12.3 11.5 10.8 10.0 9.6 1,031,200 -22.4           
 9 White Female 10.0 11.1 10.8 10.7 9.4 91 930,600 -17.4           
10 LATINO 167-185 17.3 15.2 13.7 =~ 138.2_—_—‘1,157,300 -28.7      
11 Latino Male 13.6 16.8 16.0 14.0 12.6 12.4 562,600 -26.0         
12 Latina Female 20.2 20.3 18.8 16.5 14.8 13.9 594,700 -31.5       
13 BLACK 20.4 225 224 206 17.2 17.9 999,700 -20.6                  
14 Black Male 23.7 26.0 25.6 23.5 20.1 20.8 591,600 -19.8          
15 Black Female 17.0 19.0 19.3 17.6 14.2 14.8 408,000 -22.1        
16 NATIVE AMERICAN 264 288 27.0 23 28 23.9 67,700 -17.1            
17 Native American Male 25.0 30.9 28.0 26.9 28.1 23.3 33,200 -24.5 
18 Native American Female 23.9 26.7 25.9 25.6 23.4 24.5 34,500 -B.4

Data wrangling is not an exact science. The approaches we can take are extremely dependent on the data. We can exploit patterns in the data to render the output we desire.

We will now use a cropped version of the image above without the special formatting.

# A tibble: 1 x 7
  format width height colorspace matte filesize density
  <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
1 PNG     1259    731 sRGB       TRUE    188256 72x72  
# A tibble: 1 x 7
  format width height colorspace matte filesize density
  <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
1 PNG     1259    731 sRGB       TRUE    188256 72x72  

We have several strings. Each cell of data is on a string separated by space.

We separate each string by space.

We split the dataframe in two: a labels section and a “data” section containing the information we are interested in.

In the first half, we remove all digits and punctuation to ensure that we are left with character labels.

In the second-half, remove commas and periods, converting the resulting string character class to numeric and selectively multiplying columns to reintroduce the decimal point correctly

We combine the two sections of data to create our dataframe, removing and then adding column names.

We remove columns with information we don’t need and use the commmon pattern in the column names to convert the data into long/narrow format.

We use the dplyr::case_when() and stringr::str_detect() function to detect patterns and create an separate column with gender and race information.

The two columns created contain TRUE/FALSE statements. These are then used to create a third column that will allow us to separate the data by its summary level.

The columns of character class currently contain upper and lower case characters. We want to ensure that we use a cases consistently to ensure that there are no errors driven by case-sensitive function downstream.

To do this, we use the base::to_upper() function. This function makes all characters uppercase.

Finally, we homogenize the labels assigned for certain groups, fill in missing (NA) values with a string, and remove columns we no longer need from the dataframe.

We can repeat this process for the other two tables listed on page 39.

Let’s look at the table without the special formatting.

As you can see, there are empty spaces. According to the PDF, these spaces are empty to denote that the estimates are unreliable.

This may cause problems. Whitespace must be handled differently. We may not want to process the entire image for this reason.

Instead, we can use separate images to ensure a simpler process like that above.

We read the three images.

# A tibble: 1 x 7
  format width height colorspace matte filesize density
  <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
1 PNG      757    687 sRGB       TRUE     95660 72x72  
# A tibble: 1 x 7
  format width height colorspace matte filesize density
  <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
1 PNG      751    177 sRGB       TRUE     28913 72x72  
# A tibble: 1 x 7
  format width height colorspace matte filesize density
  <chr>  <int>  <int> <chr>      <lgl>    <int> <chr>  
1 PNG      760    216 sRGB       TRUE     33402 72x72  

The images look like this.

We save the text from the images into objects.

We process these objects separately. Note that we use a very similar process to that employed in the wrangling of the previous table.

We then combine the objects with the dplyr::bind_rows() function.

The process is now very similar to the previous table.

MICHAEL ONTIVEROS

I used base R to remove the first three rows of a dataframe in the following chunk. I am not aware of a tidyverse solution for this; I am sure one exists.

Rows: 25
Columns: 5
$ Group    <chr> "UnitedStates", "Male", "Female", "ASIAN", "AsianMale", "Asi…
$ Rate     <dbl> 11.5, 11.8, 11.1, 6.6, 6.5, 6.7, 4.3, 4.7, 3.9, 5.5, 7.5, 3.…
$ Year     <dbl> 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, …
$ Gender   <lgl> NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE…
$ Subgroup <chr> "UnitedStates", NA, NA, NA, NA, NA, "CHINESE", "Chinese", "C…
Rows: 22
Columns: 6
$ Group    <chr> "ASIAN", "AsianMale", "AsianFemale", "CHINESE", "ChineseMale…
$ Rate     <dbl> 6.6, 6.5, 6.7, 4.3, 4.7, 3.9, 5.5, 7.5, 3.4, 5.9, 4.1, 7.8, …
$ Year     <dbl> 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, …
$ Gender   <lgl> NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE…
$ Subgroup <chr> NA, NA, NA, "CHINESE", "Chinese", "Chinese", "VIETNAMESE", "…
$ Type     <chr> "Asian Total", "Gender Total", "Gender Total", "Subgroup Tot…

Note that we took a process that had successfully worked for us and modified it slightly for separate, similarly-sourced data.

This is a common approach in data science. Often, the duration of the wrangling process can limit the depth of an analysis for practical reasons. Using tried methods can help reduce the time needed to wrangle data and allow time for other parts of an analysis.

Let’s add the 2018 data for this group.

We import the image.

As you can see, we have repeated newlines (\n). We can remove these with some simplex regex.

We proceed, making slight modifications to the process as needed.

The bold font appears to have caused a typos.

# A tibble: 17 x 1
   value                
   <chr>                
 1 CHINESE  41  23300   
 2 Men  45  12500       
 3 Women  37 10800      
 4 INDIAN  B44  21800   
 5 Men  47  10400       
 6 Women  61  11300     
 7 KOREAN  55  9000     
 8 Men  56  4700        
 9 Women  54  4300      
10 VIETNAMESE  63  15300
11 Men  76  9000        
12 Women  50  6400      
13 FILIPINO  68  20800  
14 Men  63  10000       
15 Women74  10800       
16 HMONG102  5300       
17 CAMBODIAN 138  4200  

We fix the typos.

# A tibble: 17 x 1
   value                
   <chr>                
 1 CHINESE  41  23300   
 2 Men  45  12500       
 3 Women  37 10800      
 4 INDIAN 54 21800      
 5 Men  47  10400       
 6 Women  61  11300     
 7 KOREAN  55  9000     
 8 Men  56  4700        
 9 Women  54  4300      
10 VIETNAMESE  63  15300
11 Men  76  9000        
12 Women  50  6400      
13 FILIPINO  68  20800  
14 Men  63  10000       
15 Women 74  10800      
16 HMONG 102  5300      
17 CAMBODIAN 138  4200  

We then continue as we would normally.

[1] 17
Rows: 17
Columns: 6
$ Group    <chr> "CHINESE", "Men", "Women", "INDIAN", "Men", "Women", "KOREAN…
$ Rate     <dbl> 4.1, 4.5, 3.7, 5.4, 4.7, 6.1, 5.5, 5.6, 5.4, 6.3, 7.6, 5.0, …
$ Year     <dbl> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, …
$ Gender   <lgl> NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE…
$ Subgroup <chr> "CHINESE", "CHINESE", "CHINESE", "INDIAN", "INDIAN", "INDIAN…
$ Type     <chr> "Subgroup Total", "Subgroup Total", "Subgroup Total", "Subgr…

The dataframe we produced does not contain totals.

# A tibble: 17 x 5
    Rate  Year Gender Subgroup   Type          
   <dbl> <dbl> <chr>  <chr>      <chr>         
 1   4.1  2018 ALL    CHINESE    SUBGROUP TOTAL
 2   4.5  2018 MALE   CHINESE    SUBGROUP TOTAL
 3   3.7  2018 FEMALE CHINESE    SUBGROUP TOTAL
 4   5.4  2018 ALL    INDIAN     SUBGROUP TOTAL
 5   4.7  2018 MALE   INDIAN     SUBGROUP TOTAL
 6   6.1  2018 FEMALE INDIAN     SUBGROUP TOTAL
 7   5.5  2018 ALL    KOREAN     SUBGROUP TOTAL
 8   5.6  2018 MALE   KOREAN     SUBGROUP TOTAL
 9   5.4  2018 FEMALE KOREAN     SUBGROUP TOTAL
10   6.3  2018 ALL    VIETNAMESE SUBGROUP TOTAL
11   7.6  2018 MALE   VIETNAMESE SUBGROUP TOTAL
12   5    2018 FEMALE VIETNAMESE SUBGROUP TOTAL
13   6.8  2018 ALL    FILIPINO   SUBGROUP TOTAL
14   6.3  2018 MALE   FILIPINO   SUBGROUP TOTAL
15   7.4  2018 FEMALE FILIPINO   SUBGROUP TOTAL
16  10.2  2018 ALL    HMONG      SUBGROUP TOTAL
17  13.8  2018 ALL    CAMBODIAN  SUBGROUP TOTAL

We can find these totals in the PDF directly and create rows as needed

We load the PDF.

We add the rows.

We repeat this process again for Latino/a subgroups.

The table, without the special formatting, looks like this.

There are no whitespaces in this table.

We proceed using what we’ve learned while wrangling the first two tables.

# A tibble: 17 x 1
   value                              
   <chr>                              
 1 LATINO 13.2 1,157,300              
 2 Latino Male 12.4 562,600           
 3 Latina Female 13.9 594,700         
 4 SOUTH AMERICAN 8.4 37,600          
 5 South American Male 9.1 20,400     
 6 South American Female 17 17,200    
 7 CENTRAL AMERICAN 12.0 93,100       
 8 Central American Male 9.3 37,900   
 9 Central American Female 15.0 55,200
10 MEXICAN 13.3 762,400               
11 Mexican Male 12.2 358,200          
12 Mexican Female 14.4 404,200        
13 OTHER LATINO 13.6 44,800           
14 Other Latino Male 15.3 27,600      
15 Other Latina Female 11.5 17,300    
16 PR, DR, Cuban Female 15.7 114,500  
17 PR, DR, Cuban Female 14.4 96,600   

We are often presented with scenarios where stand-alone approaches are difficult or time-consuming.

It is always best to document the steps take to respond to these scenarios. Wrangling this third table is a prime example of this.

We are missing a row. Let’s manually add the row.

We can now proceed as we did with the previous tables.

If we look at the last few rows, we see that there is a typo. There are two female groups.

# A tibble: 6 x 3
  Group              Rate N_2017
  <chr>             <dbl>  <dbl>
1 OTHERLATINO        13.6  44800
2 OtherLatinoMale    15.3  27600
3 OtherLatinaFemale  11.5  17300
4 PRDRCubanFemale    15.7 114500
5 PRDRCubanFemale    14.4  96600
6 PRDRCuban          15.1 211200

Sometimes when wrangling text data, we will come across a typo. We need to determine how to respond to the typo and make note of it. It’s often best to consult a secondary source to confirm that changes made are accurate.

For the purposes of this case study, we will assume that the first of the two rows represents male disconnection rates in the Latino/a subgroup; this would be consistent with the ordering of genders in the previous subgroups.

Let’s make the correction to the typo.

It looks like we’ve succesfully corrected the typo.

# A tibble: 6 x 3
  Group              Rate N_2017
  <chr>             <dbl>  <dbl>
1 OTHERLATINO        13.6  44800
2 OtherLatinoMale    15.3  27600
3 OtherLatinaFemale  11.5  17300
4 PRDRCubanMale      15.7 114500
5 PRDRCubanFemale    14.4  96600
6 PRDRCuban          15.1 211200

We can continue with the process we’ve developed now that we have made the correction.

Rows: 18
Columns: 5
$ Group    <chr> "LATINO", "LatinoMale", "LatinaFemale", "SOUTHAMERICAN", "So…
$ Rate     <dbl> 13.2, 12.4, 13.9, 8.4, 9.1, 1.7, 12.0, 9.3, 15.0, 13.3, 12.2…
$ Year     <dbl> 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, …
$ Gender   <lgl> NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE…
$ Subgroup <chr> NA, NA, NA, "SOUTHAMERICAN", "SouthAmerican", "SouthAmerican…
Rows: 18
Columns: 6
$ Group    <chr> "LATINO", "LatinoMale", "LatinaFemale", "SOUTHAMERICAN", "So…
$ Rate     <dbl> 13.2, 12.4, 13.9, 8.4, 9.1, 1.7, 12.0, 9.3, 15.0, 13.3, 12.2…
$ Year     <dbl> 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, 2017, …
$ Gender   <lgl> NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE…
$ Subgroup <chr> NA, NA, NA, "SOUTHAMERICAN", "SouthAmerican", "SouthAmerican…
$ Type     <chr> "Latino/a Total", "Gender Total", "Gender Total", "Subgroup …

Let’s add the 2018 data to this dataframe.

We import the image.

As you can see, we have repeated newlines (\n). We can remove these with some simplex regex.

We proceed, making slight modifications to the process as needed.

[1] 12
Rows: 12
Columns: 6
$ Group    <chr> "SOUTHAMERICAN", "Men", "Women", "MEXICAN", "Men", "Women", …
$ Rate     <dbl> 8.0, 7.5, 8.6, 12.9, 12.0, 13.8, 13.7, 14.9, 12.4, 13.7, 11.…
$ Year     <dbl> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, …
$ Gender   <lgl> NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE, TRUE, NA, FALSE…
$ Subgroup <chr> "SOUTHAMERICAN", "SOUTHAMERICAN", "SOUTHAMERICAN", "MEXICAN"…
$ Type     <chr> "Subgroup Total", "Subgroup Total", "Subgroup Total", "Subgr…

We load the PDF.

We add the rows.

We add the 2018 data to the dataframe

Map

We will use multiple images to import the data on page 36 to produce maps.

MICHAEL ONTIVEROS

This code is not complete. If there is time, we will return to it! Magick is having trouble with quadrant 1 and 4. I could not figure out why.

Data Analysis


Repeated Cross-sectional Data

We have pooled (repeated) cross-sectional data.

This is data produced from repeated measurement of a population over time.

It is often infeasible to collect data for an entire population at once. However, we can still obtain meaningful measures using a random sample of the population.

At specific time-points, data is collected from a sample of the population. The individuals in each sample are not necessarily the same individuals. This separates pooled cross-sectional data from panel data, which is longitudinal data from repeated measurement of the same people.

By sampling from a population at multiple time points, we can generate population level statistics. Although these statistics have some random error, they can provide insight into how the measure variable is changing in a population over time.

We can accomplish this by plotting the measured values over time. Sometimes, however, the trend isn’t exactly clear. Fortunately, there are statistical methods to resolve this issue.

The Mann-Kendall trend test—a variation of the Kendall rank correlation coefficient—tests whether there is a monotonic association, an association that does not increase or decrease but remains static across a dimension.

Recall the youth disconnection rates for Native Americans, some of the highest in the first table we examined.

Let’s conduct a Mann-Kendall test for trend.

We can accomplish this with the Kendall::MannKendall() function. The Kendall::MannKendall() accepts a vector of data for which a trend may be observed. Consulting the documentation for the Kendall::MannKendall() function available on CRAN, we can “test for a a monotonic trend in a time series”.

Score =  -7 , Var(Score) = 28.33333
denominator =  15
tau = -0.467, 2-sided pvalue =0.25966

There does not appear to be a change in the trend. However, it’s important to note that we only have 6 observations.

We can also explore the trend using simple linear regression.


Call:
lm(formula = Rate ~ Year, data = .)

Residuals:
      1       2       3       4       5       6 
-2.4332  2.2978  0.8288  0.4597  0.2907 -1.4438 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept) 359.1159   487.3956   0.737    0.502
Year         -0.1655     0.2421  -0.683    0.532

Residual standard error: 1.889 on 4 degrees of freedom
Multiple R-squared:  0.1045,    Adjusted R-squared:  -0.1193 
F-statistic: 0.467 on 1 and 4 DF,  p-value: 0.5319

For each one year change, the mean increase in disconnection rates is -0.1654795. This relationship is not statistically significant. Again, we are largely limited by the number of observations in this dataset.

We can visualize the relationship above.

As we can see, there is a large amount of uncertainty around the fitted line.

Let’s visualize the data!

Data Visualization


Let’s reproduce the example below.

We can create a version of the above example with ggplot from tidyverse.

There are color identifying websites only such as this.

Using one of these websites, we identify the hex triplet for the color used in the visualization included in the PDF: #008393.

We can build off of this idea, using a custom color palette to create a gradient based off the color used.

From the above plot, it becomes apparent that the Hmong subgroup produces a small proportion of the total number of asian disconnected youth. The Asian total youth disconnection rate is more alike the youth disconnection rates for all other subgroups than the Hmong youth disconnection rate.

We can confirm this by revisiting the table.

The Hmong group represents 6% of all Asian disconnected youth.

This shows the importance of adding small details such as the composite line to plots. It helps provide a simple yet nuanced picture of what is going on.

Lastly, we can add annotations to add provide even more depth to the visualization.

Summary


Suggested Homework


  1. Find another table in the document. Find differences between groups with the process described above.

Acknowledgements

We would like to acknowledge Tamar Mendelson for assisting in framing the major direction of the case study.

We would also like to acknowledge the Bloomberg American Health Initiative for funding this work.

LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBEaXNwYXJpdGllcyBpbiBZb3V0aCBEaXNjb25uZWN0aW9uIgpjc3M6IHN0eWxlLmNzcwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwoKLS0tCgo8c3R5bGU+CiNUT0MgewogIGJhY2tncm91bmQ6IHVybCgiaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvL2ltZy9sb2dvLmpwZyIpOwogIGJhY2tncm91bmQtc2l6ZTogY29udGFpbjsKICBwYWRkaW5nLXRvcDogMjQwcHggIWltcG9ydGFudDsKICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Owp9Cjwvc3R5bGU+CgoKCgoKCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNmZmNjY2I7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqTUlDSEFFTCBPTlRJVkVST1MqKgoKKlRoZXJlIGFyZSBzb21lIGV4aXN0aW5nIHR5cG9zIGluIHRoZSB0YWJsZXMgaW4gYWRkaXRpb24gdG8gdGhvc2UgcHJvZHVjZWQgZHVyaW5nIHRoZSB1c2Ugb2YgTWFnaWNrLiBJIG1hZGUgc29tZSBhc3N1bXB0aW9ucyBhbG9uZyB0aGUgd2F5LCBkb2N1bWVudGluZyB0aGVtLiBUaGVzZSBuZWVkIHRvIGJlIGNoZWNrZWQgZm9yIGFjY3VyYWN5LioKPC9kaXY+CgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGluY2x1ZGUgPSBUUlVFLCBjb21tZW50ID0gTkEsIGVjaG8gPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIiwgb3V0LndpZHRoID0gJzkwJScpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShrbml0cikKYGBgCgoKIyMjIyB7Lm91dGxpbmUgfQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGggPSAiODAwIHB4IiwgZXZhbD1GQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIm1haW5wbG90LnBuZyIpKQpgYGAKCiMjIyMKCiMjIHsuZGlzY2xhaW1lcl9ibG9ja30KCioqRGlzY2xhaW1lcioqOiBUaGUgcHVycG9zZSBvZiB0aGUgW09wZW4gQ2FzZSBTdHVkaWVzXShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8pe3RhcmdldD0iX2JsYW5rIn0gcHJvamVjdCBpcyAqKnRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdmFyaW91cyBkYXRhIHNjaWVuY2UgbWV0aG9kcywgdG9vbHMsIGFuZCBzb2Z0d2FyZSBpbiB0aGUgY29udGV4dCBvZiBtZXNzeSwgcmVhbC13b3JsZCBkYXRhKiouIEEgZ2l2ZW4gY2FzZSBzdHVkeSBkb2VzIG5vdCBjb3ZlciBhbGwgYXNwZWN0cyBvZiB0aGUgcmVzZWFyY2ggcHJvY2VzcywgaXMgbm90IGNsYWltaW5nIHRvIGJlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byBhbmFseXplIGEgZ2l2ZW4gZGF0YSBzZXQsIGFuZCBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhlIGNvbnRleHQgb2YgbWFraW5nIHBvbGljeSBkZWNpc2lvbnMgd2l0aG91dCBleHRlcm5hbCBjb25zdWx0YXRpb24gZnJvbSBzY2llbnRpZmljIGV4cGVydHMuIAoKCiMjIHsubGljZW5zZV9ibG9ja30KClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBbKENDIEJZLU5DIDMuMCldKGh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvdXMvKXt0YXJnZXQ9Il9ibGFuayJ9ICBVbml0ZWQgU3RhdGVzIExpY2Vuc2UuCgoKIyMgey5yZWZlcmVuY2VfYmxvY2t9CgpUbyBjaXRlIHRoaXMgY2FzZSBzdHVkeSBwbGVhc2UgdXNlOgoKV3JpZ2h0LCBDYXJyaWUsIGFuZCBPbnRpdmVyb3MsIE1pY2hhZWwgYW5kIEphZ2VyLCBMZWFoIGFuZCBUYXViLCBNYXJnYXJldCBhbmQgSGlja3MsIFN0ZXBoYW5pZS4gKDIwMjApLiBodHRwczovL2dpdGh1Yi5jb20vb3BlbmNhc2VzdHVkaWVzL29jcy15b3V0aC1kaXNjb25uZWN0aW9uLWNhc2Utc3R1ZHkuIERpc3Bhcml0aWVzIGluIFlvdXRoIERpc2Nvbm5lY3Rpb24gKFZlcnNpb24gdjEuMC4wKS4KCiMjICoqTW90aXZhdGlvbioqCioqKiAKCkFjY29yZGluZyB0byB0aGlzIFtyZXBvcnRdKGh0dHBzOi8vc3NyYy1zdGF0aWMuczMuYW1hem9uYXdzLmNvbS9tb2EvTWFraW5nJTIwdGhlJTIwQ29ubmVjdGlvbi5wZGYpIHlvdXRoIGRpc2Nvbm5lY3Rpb24gYWx0aG91Z2ggZ2VuZXJhbGx5IHNob3dpbmcgZGVjcmVhc2luZyB0cmVuZHMgZm9yIHRoZSBwYXN0IDcgeWVhcnMsIHNob3dzICoqcmFjaWFsIGFuZCBldGhuaWMgZGlzcGFyaXRpZXMqKiwgd2hlcmUgc29tZSBncm91cHMgYXJlIHNob3dpbmcgaW5jcmVhc2VkIHJhdGVzIG9mIGRpc2Nvbm5lY3Rpb24uCgpTbyB3aGF0IGRvZXMgdGhlIHRlcm0gKioieW91dGggZGlzY29ubmVjdGlvbiIqKiBtZWFuPwoKQWNjb3JkaW5nIHRvIFtNZWFzdXJlIG9mIEFtZXJpY2FdKGh0dHBzOi8vd3d3LnNzcmMub3JnL3Byb2dyYW1zL3ZpZXcvbW9hLyl7dGFyZ2V0PSJfYmxhbmsifSAoYSBub25wYXJ0aXNhbiBwcm9qZWN0IG9mIHRoZSBub25wcm9maXQgW1NvY2lhbCBTY2llbmNlIFJlc2VhcmNoIENvdW5jaWxdKGh0dHBzOi8vd3d3LnNzcmMub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSB0aGF0IGlzIGZvY3VzZWQgb24gb3Bwb3J0dW5pdHkgaW4gdGhlIFVuaXRlZCBTdGF0ZXMpIGRpc2Nvbm5lY3RlZCB5b3V0aCBhcmU6Cgo+ICJ5b3VuZyBwZW9wbGUgYmV0d2VlbiB0aGUgYWdlcyBvZiAqKjE2IGFuZCAyNCoqIHdobyBhcmUgKipuZWl0aGVyIHdvcmtpbmcgbm9yIGluIHNjaG9vbCoqIgoKVGhleSBzdGF0ZSB0aGF0IHN1Y2ggZGlzY29ubmVjdGlvbiBoaW5kZXJzIHRoZXNlIGluZGl2aWR1YWxzIHRvIGFxdWlyZSBza2lsbHMgYW5kIGNyZWF0ZSByZWxhdGlvbnNoaXBzIG5lY2Vzc2FyeSB0byBoYXZlIGEgc3VjZXNzZnVsIGFkdWx0aG9vZC4gCgpUaGV5IHN0YXRlIHRoYXQ6Cgo+ICJwZW9wbGUgd2hvIGV4cGVyaWVuY2UgYSBwZXJpb2Qgb2YgZGlzY29ubmVjdGlvbiBhcyB5b3VuZyBhZHVsdHMgZ28gb24gdG8gKiplYXJuIGxlc3MqKiBhbmQgYXJlICoqbGVzcyBsaWtlbHkqKiB0byBiZSAqKmVtcGxveWVkLCBvd24gYSBob21lLCBvciByZXBvcnQgZ29vZCBoZWFsdGgqKiBieSB0aGUgdGltZSB0aGV5IHJlYWNoIHRoZWlyIHRoaXJ0aWVzIgoKRGlzY29ubmVjdGVkIHlvdXRoIGFyZSBhbHNvIHJlZmVycmVkIHRvIGFzICoqb3Bwb3J0dW5pdHkgeW91dGgqKiwgd2hpY2ggaGFzIHRoZSBhZGRlZCBwb3NpdGl2ZSBjb25ub3RhdGlvbiB0aGF0IHByb21vdGluZyBzdWNoIGluZGl2aWR1YWxzIGNhbiBiZSBiZW5lZmljaWFsIG5vdCBvbmx5IGZvciB0aGVzZSBpbmRpdmlkdWFscyBidXQgYWxzbyBmb3IgdGhlaXIgY29tbXVudGllcyBhbmQgZm9yIHNvY2lldHkuIAoKV2Ugd2lsbCBleHBhbmQgYmV5b25kIHRoZSBbTWVhc3VyZSBvZiBBbWVyaWNhIGFubnVhbCByZXBvcnRdKGh0dHBzOi8vc3NyYy1zdGF0aWMuczMuYW1hem9uYXdzLmNvbS9tb2EvTWFraW5nJTIwdGhlJTIwQ29ubmVjdGlvbi5wZGYpe3RhcmdldD0iX2JsYW5rIn0gdG8gdGFrZSBhIGRlZXBlciBsb29rIGF0IGRpZmZlcmVuY2VzIG9mIHNwZWNpZmljIGdyb3VwcyBvZiB5b3V0aHMuIElkZW50aWZ5aW5nIHlvdXRocyBwYXJ0aWN1bGFybHkgYXQgcmlzayBvciBkaXNjb25uZWN0ZWQsIGNhbiBoZWxwIGluZm9ybSB0aGUgZGVzaWduIG9mIHRhcmdldGVkIHByZXZlbnRpb24gYW5kIHJlbmdhZ2VtZW50IHN0cmF0ZWdpZXMuCgpUaGlzIGNhc2Ugc3R1ZHkgaXMgbW90aXZhdGVkIGJ5IHRoaXMgW2FydGljbGVdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzYyNDM0NDYvKXt0YXJnZXQ9Il9ibGFuayJ9OiAKCiMjIyMgey5yZWZlcmVuY2VfYmxvY2t9CgpNZW5kZWxzb24sIFQuLCBNbWFyaSwgSy4sIEJsdW0sIFIuIFcuLCBDYXRhbGFubywgUi4gRi4gJiBCcmluZGlzLCBDLiBELiBPcHBvcnR1bml0eSBZb3V0aDogSW5zaWdodHMgYW5kIE9wcG9ydHVuaXRpZXMgZm9yIGEgUHVibGljIEhlYWx0aCBBcHByb2FjaCB0byBSZWVuZ2FnZSBEaXNjb25uZWN0ZWQgVGVlbmFnZXJzIGFuZCBZb3VuZyBBZHVsdHMuICpQdWJsaWMgSGVhbHRoIFJlcCogMTMzLCA1NFMtNjRTICgyMDE4KS4KCiMjIyMKIApUaGlzIFthcnRpY2xlXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM2MjQzNDQ2Lyl7dGFyZ2V0PSJfYmxhbmsifSBkZXNjcmliZXMgc3RyYXRlZ2llcyBmb3IgcHJldmVudGlvbiBvZiBkaXNjb25uZWN0aW9uIGFuZCByZWVuZ2FnZW1lbnQgb2YgZGlzY2Nvbm5lY3RlZCB5b3V0aCBhbmQgaG93IHN1Y2ggaW50ZXJ2ZW50aW9ucyBjb3VsZCBncmVhdGx5IHBvc2l0aXZlbHkgaW1wYWN0IG9wcG9ydHVuaXR5IHlvdXRoIGZvciB0aGUgZW50aXJlIHRyYWplY3Rvcnkgb2YgdGhlaXIgbGl2ZXMgYW5kIGZvciBmdXR1cmUgZ2VuZXJhdGlvbnMuIEl0IGFsc28gcG9pbnRzIG91dCB0aGF0IGluZGVlZCB0aGVpciBhcmUgZGlzcGFyaXRpZXMgYW1vbmcgZGlmZmVyZW50IHJhY2lhbC9ldGhuaWMgZ3JvdXBzLgoKCiMjICoqTWFpbiBRdWVzdGlvbnMqKgoqKiogCgojIyMjIHsubWFpbl9xdWVzdGlvbl9ibG9ja30KPGI+PHU+IE91ciBtYWluIHF1ZXN0aW9uczogPC91PjwvYj4KCjEpIEhvdyBoYXZlIHlvdXRoIGRpc2Nvbm5lY3Rpb24gcmF0ZXMgaW4gQW1lcmljYW4geW91dGggY2hhbmdlZCBzaW5jZSAyMDA4PyAgIAoyKSBJbiBwYXJ0aWN1bGFyLCBob3cgaGFzIHRoaXMgY2hhbmdlZCBmb3IgZGlmZmVyZW50IGdlbmRlciBhbmQgZXRobmljIGdyb3Vwcz8gQXJlIGFueSBncm91cHMgcGFydGljdWxhcmx5IGRpc2Nvbm5lY3RlZD8gCgojIyMjCgojIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKiAKKioqIAoKSW4gdGhpcyBjYXNlIHN0dWR5LCB3ZSB3aWxsIGRlbW9uc3RyYXRlIGhvdyB0byBpbXBvcnQgYW5kIHdyYW5nbGUgZGF0YSBhdmFpbGFibGUgaW4gdGhlIDx1PioqUCoqPC91Pm9ydGFibGUgPHU+KipEKio8L3U+b2N1bWVudCA8dT4qKkYqKjwvdT5vcm1hdCAoKipQREYqKikuIFdlIHdpbGwgZXNwZWNpYWxseSBmb2N1cyBvbiB1c2luZyBwYWNrYWdlcyBhbmQgZnVuY3Rpb25zIGZyb20gdGhlIFtgVGlkeXZlcnNlYF0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0sIHN1Y2ggYXMgYGRwbHlyYCwgYGdncGxvdDJgLiBUaGUgdGlkeXZlcnNlIGlzIGEgbGlicmFyeSBvZiBwYWNrYWdlcyBjcmVhdGVkIGJ5IFJTdHVkaW8uIFdoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBlc3BlY2lhbGx5IGVmZmljaWVudC4KClRoZSBza2lsbHMsIG1ldGhvZHMsIGFuZCBjb25jZXB0cyB0aGF0IHN0dWRlbnRzIHdpbGwgYmUgZmFtaWxpYXIgd2l0aCBieSB0aGUgZW5kIG9mIHRoaXMgY2FzZSBzdHVkeSBhcmU6CgpEYXRhIHNjaWVuY2Ugc2tpbGxzOiAgCgoxLiBJbXBvcnRpbmcgZGF0YSBmcm9tIFBERiBmaWxlcyB1c2luZyB0aGUgYG1hZ2lja2AgcGFja2FnZSAgCjIuIEFwcGx5IGFjdGlvbiB2ZXJicyBpbiBgZHBseXJgIGZvciBkYXRhIHdyYW5nbGluZyAgCjMuIEhvdyB0byBwaXZvdCBiZXR3ZWVuICJsb25nIiBhbmQgIndpZGUiIGRhdGFzZXRzIChgdGlkeXJgKSAgCjQuIEpvaW5pbmcgdG9nZXRoZXIgbXVsdGlwbGUgZGF0YXNldHMgdXNpbmcgYGRwbHlyYCAgCjUuIEhvdyB0byBjcmVhdGUgZGF0YSB2aXN1YWxpemF0aW9ucyB3aXRoIGBnZ3Bsb3QyYCB0aGF0IGFyZSBpbiBhIHNpbWlsYXIgc3R5bGUgdG8gYW4gZXhpc3RpbmcgaW1hZ2UgIAoKU3RhdGlzdGljYWwgY29uY2VwdHMgYW5kIG1ldGhvZHM6ICAKCjEuIEltcGxlbWVudGF0aW9uIG9mIHRoZSBNYW5uLUtlbmRhbGwgdHJlbmQgdGVzdCAgCjIuIEludGVycHJldGF0aW9uIG9mIHRoZSBNYW5uLUtlbmRhbGwgdHJlbmQgdGVzdCAgCgoKYGBge3IsIG91dC53aWR0aCA9ICIyMCUiLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vdGlkeXZlcnNlLnRpZHl2ZXJzZS5vcmcvbG9nby5wbmciKQpgYGAKCioqKiAKCldlIHdpbGwgYmVnaW4gYnkgbG9hZGluZyB0aGUgcGFja2FnZXMgdGhhdCB3ZSB3aWxsIG5lZWQ6CgpgYGB7cn0KbGlicmFyeShoZXJlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShwZGZ0b29scykKbGlicmFyeShtYWdpY2spCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShLZW5kYWxsKQpgYGAKCgoKIFBhY2thZ2UgICB8IFVzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbKipoZXJlKipdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEKWyoqdGlkeXZlcnNlKipdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IGZvciBkYXRhIHNjaWVuY2Ugb3BlcmF0aW9ucwpbKipwZGZ0b29scyoqXShodHRwczovL3JlYWRyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBtYW5hZ2UgUERGIGRvY3VtZW50cwpbKiptYWdpY2sqKl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ2ljay92aWduZXR0ZXMvaW50cm8uaHRtbCNLZXJuZWxfY29udm9sdXRpb24pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IGZvciBpbWFnZSBwcm9jZXNzaW5nIAoKVGhlIGZpcnN0IHRpbWUgd2UgdXNlIGEgZnVuY3Rpb24sIHdlIHdpbGwgdXNlIHRoZSBgOjpgIHRvIGluZGljYXRlIHdoaWNoIHBhY2thZ2Ugd2UgYXJlIHVzaW5nLiBVbmxlc3Mgd2UgaGF2ZSBvdmVybGFwcGluZyBmdW5jdGlvbiBuYW1lcywgdGhpcyBpcyBub3QgbmVjZXNzYXJ5LCBidXQgd2Ugd2lsbCBpbmNsdWRlIGl0IGhlcmUgdG8gYmUgaW5mb3JtYXRpdmUgYWJvdXQgd2hlcmUgdGhlIGZ1bmN0aW9ucyB3ZSB3aWxsIHVzZSBjb21lIGZyb20uCgojIyAqKkNvbnRleHQqKgoqKiogCgpTbyBob3cgZG9lcyB5b3V0aCBkaXNjb25uZWN0aW9uIGhhcHBlbiBhbmQgd2hhdCBpbXBhY3QgZG9lcyBpdCBoYXZlPwoKClRoZXJlIGFyZSBtYW55IGtub3duICoqcmlzayBmYWN0b3JzKiosIHdoaWNoIGhhdmUgYmVlbiBpZGVudGlmaWVkIGluIGEgdmFyaWV0eSBvZiBjb250ZXh0cyAoZnJvbSBmYW1pbHksIGZyaWVuZHMsIHNjaG9vbCwgY29tbXVuaXR5LCBzb2NpZXR5KSBpbmNsdWRpbmc6ICAKCiAtIHBvdmVydHkgKGRpc2Nvbm5lY3RlZCB5b3V0aCBhcmUgbmVhcmx5IHR3aWNlIGFzIGxpa2VseSB0byBsaXZlIGluIHBvdmVydHkgYW5kIHJlY2VpdmUgTWVkaWNhaWQpICAKIC0gcmFjaWFsL2V0aG5pYyBkaXNwYXJpdGllcyAoZmluZGluZ3Mgc3VnZ2VzdCB0aGF0IHRoZXNlIHBlcnNpc3QgZXZlbiB3aGVuIGNvbnRyb2xsaW5nIGZvciBpbmNvbWUpICAKIC0gcmVzaWRlbnRpYWwgZW52aXJvbm1lbnQgKGluIDIwMTYgd2hpbGUgMTEuNyUgd2FzIHRoZSBuYXRpb25hbCBhdmVyYWdlLCAyNCUgb2YgcGVvcGxlIGFnZSAxNi0yNCBpbiB0aGUgcnVyYWwgU291dGggd2VyZSBkaXNjb25uZWN0ZWQpICAKIC0gcG9vciBhY2FkZW1pYyBwZXJmb3JtYW5jZSAgCiAtIHBvb3IgbWVudGFsIGhlYWx0aCAgCiAtIHN1YnN0YW5jZSB1c2UgZGlzb3JkZXJzICAKIC0gcGFyZW50YWwgdW5lbXBsb3ltZW50ICAKIC0gdHJhdW1hIGV4cG9zdXJlICAKIC0gYXNzb2NpYXRpb24gd2l0aCBzb2NpYWxseSBkZXZpYW50IHBlZXJzIAogLSBzY2hvb2wgcG9saWNpZXMgc3VjaCBhcyAib25lIHN0cmlrZSBhbmQgeW91J3JlIG91dCIgLSB3aGljaCBpcyBhIHplcm8gdG9sZXJhbmNlIHNjaG9vbCBleHB1bHNpb24gcG9saWN5IGFuZCBzaG93biB0byBpbmNyZWFzZSBkcm9wb3V0cyBhbmQgaW5jYXJjZXJhdGlvbiByYXRlcwogCiBUaGVzZSByaXNrIGZhY3RvcnMgbWFrZSBpdCBtb3JlIGxpa2VseSBmb3IgeW91bmcgcGVvcGxlIHRvIG1pc3Mgb3V0IG9uIGVkdWNhdGlvbiwgdHJhaW5pbmcsIGFuZCBuZXR3b3JraW5nIHRoYXQgY2FuIGFjdCBhcyBhIGZvdW5kYXRpb24gZm9yIGEgc3VjZXNzZnVsIGNhcmVlci4KIApUaGVyZSBhcmUgYWxzbyBtYW55IGtub3duICoqbmVnYXRpdmUgY29uc2VxdWVuY2VzKiogYXNzb2NpYXRlZCB3aXRoIHlvdXRoIGRpc2Nvbm5lY3Rpb24gaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZCB0bzoKCi0gY2hyb25pYyB1bmVtcGxveW1lbnQKLSBwb3ZlcnR5Ci0gcG9vciBtZW50aGFsIGhlYWx0aCBhbmQgcG9vciBnZW5lcmFsIGhlYWx0aCAoaW4gYSAyMDAyIHN0dWR5IC0geW91dGhzIGRpc2Nvb25lY3RlZCBmb3IgNiBvciBtb3JlIG1vbnRocyB3ZXJlIDMgdGltZXMgbW9yZSBsaWtlbHkgdG8gZGV2ZWxvcCBkZXByZXNzaW9uIG9yIG90aGVyIG1lbnRhbCBoZWFsdGggZGlzb3JkZXIpCi0gY3JpbWlhbCBiZWhhdmlvciAoaW4gYSAyMDAyIHN0dWR5IC0geW91dGhzIGRpc2Nvb25lY3RlZCBmb3IgNiBvciBtb3JlIG1vbnRocyB3ZXJlIDUgdGltZXMgbW9yZSBsaWtlbHkgdG8gaGF2ZSBhIGNyaW1pbmFsIHJlY29yZCkKLSBpbmNhcmNlcmF0aW9uCi0gZWFybHkgbW9ydGFsaXR5IAoKCmBgYHtyLCBvdXQud2lkdGg9ICI0MDBweCIsZWNobz1GQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgImpvbi10eXNvbi1hanpOMkFZTmkxVS11bnNwbGFzaC5qcGciKSkKYGBgCjxzcGFuPlBob3RvIGJ5IDxhIGhyZWY9Imh0dHBzOi8vdW5zcGxhc2guY29tL0Bqb250eXNvbj91dG1fc291cmNlPXVuc3BsYXNoJmFtcDt1dG1fbWVkaXVtPXJlZmVycmFsJmFtcDt1dG1fY29udGVudD1jcmVkaXRDb3B5VGV4dCI+Sm9uIFR5c29uPC9hPiBvbiA8YSBocmVmPSJodHRwczovL3Vuc3BsYXNoLmNvbS9zL3Bob3Rvcy91bmVtcGxveW1lbnQ/dXRtX3NvdXJjZT11bnNwbGFzaCZhbXA7dXRtX21lZGl1bT1yZWZlcnJhbCZhbXA7dXRtX2NvbnRlbnQ9Y3JlZGl0Q29weVRleHQiPlVuc3BsYXNoPC9hPjwvc3Bhbj4KCkZ1cnRoZXJtb3JlLCBpbiAyMDEyIGl0IHdhcyBlc3RpbWF0ZWQgdGhhdCBlYWNoIGRpc2Nvbm5lY3RlZCB5b3V0aCBjb3N0cyB0YXhwYXllcnMgJDI1MDAwMCBkdXJpbmcgYSBsaWZlIHRpbWUgZHVlIHRvIGxvc3QgdGF4IHJldmVudWUgYW5kIGNvc3RzIGZvciBzb2NpYWwgc2VyY2ljZXMsIGhlYXRoIGNhcmUgYW5kIGNyaW1pbmFsIGp1c3RpY2UuCgpZb3V0aCBkaXNjb25uZWN0aW9uIGNhbiBiZSBkZXNjcmliZWQgYXMgYSBjb250aW51dW0sIGFzIHNvbWUgeW91dGhzIHdpbGwgYmUgZGlzY29ubmVjdGVkIGZvciBhIGJyaWVmIHRpbWUsIHdoaWxlIG90aGVycyBhcmUgY2hyb25pY2FsbHkgZGlzY29ubmVjdGVkLiBBZGRpdGlvbmFsbHksIHdoaWxlIGFuIGluZGl2aWR1YWwgd2hvIGlzIG91dCBvZiBzY2hvb2wgYW5kIHdvcmsgYW5kIGFsc28gaGFzIHBvb3Igc3VwcG9ydCBmcm9tIHRoZSByZWFsdGlvbnNoaXBzIG9mIG90aGVycyBtYXkgYmUgZnVydGhlciBkaXNjb25uZWN0ZWQgdGhhbiBhbiBpbmRpdmlkdWFsIHdobyBoYXMgc29jaWFsIHN1cHBvcnQuCgpIZXJlIGlzIGFuIGlsbHVzdHJhdGlvbiBvZiByaXNrIGZhY3RvcnMsIHByb3RlY3RpdmUgZmFjdG9ycyBhbmQgdGhlIGNvbnRpbnV1bSBvZiBkaXNjb25uZWN0aW9uOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjgwMCBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJyaXNrX2ZhY3RvcnMucG5nIikpCmBgYAojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzYyNDM0NDYvcGRmLzEwLjExNzdfMDAzMzM1NDkxODc5OTM0NC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gCgoKIyMjIFN0cmF0ZWdpZXMgdG8gbWl0aWdhdGUgeW91dGggZGlzY29ubmVjdGlvbgoKTWFueSBwcm9ncmFtcyBoYXZlIGlkZW50aWZpZWQgdXNlZnVsIHN0cmF0ZWdpZXMgaW4gcmVuZ2FnaW5nIGRpc2Nvbm5lY3RlZCB5b3V0aCBvciBwcmV2ZW50aW5nIGRpc2Njb25lY3Rpb24gb2YgeW91dGguIAoKZ2VuZXJhbGx5IHNwZWFraW5nLCBtb3N0IHByb2dyYW1zIGZvY3VzIG9uIHJlZW5nYWdlbWVudCBzdHJhdGVnaWVzLCBob3dldmVyLCBwcmV2ZW50aW9uIHN0cmF0ZWdpZXMgYXJlIGxpa2VseSB0byBiZSBqdXN0IGFzIGltcG9ydGFudC4gCgpSZXNlcmFjaCBzdWdnZXN0cyB0aGF0IGFjdGl2ZSBpbnZvbHZlbWVudCB3aXRoIGF0IHJpc2sgeW91dGggZnJvbSBpbmZhbmN5IGFuZCBhY3Jvc3MgbXVsdGlwbGUgZGV2ZWxvcG1lbnRhbCBzdGFnZXMgdGhyb3VnaCB5b3VuZyBhZHVsdGhvb2Qgd2hvdWxkIGJlIHRoZSBtb3N0IGJlbmVmaWNpYWwuCgpJbiBmYWN0LCB0aGUgcXVhbGl0eSBvZiBwYXJlbnRhbCBjYXJlZ2l2aW5nIG9mIGluZmFudHMgYWdlIDYtMjQgbW9udGhzIGhhcyBhY3R1YWxseSBiZWVuIHNob3duIHRvIGJlIGEgcHJlZGljdG9yIG9mIGhpZ2ggc2Nob29sIGRyb3BvdXQgcmF0ZXMhIFRodXMgZWFybHkgaW50ZXJ2ZW50aW9ucyBtYXkgYmUgdmVyeSBpbXBvcnRhbnQgYW5kIGNvbnNpc3RlbnQgY29udGludWFsIGVuZ2FnZW1lbnQgbWF5IHByZXZlbnQgZnVydGhlciBkaXNjb25uZWN0aW9uIG9mIHlvdXRocy4KClByZXZlbnRpb24gc3RyYXRlZ2llcyBpbmNsdWRlOiAgCgotIFByZXNjaG9vbCAgCi0gW1RoZSBHb29kIEJlaGF2aW9yIEdhbWVdKGh0dHBzOi8vd3d3Lmdvb2RiZWhhdmlvcmdhbWUub3JnL2dvb2QtYmVoYXZpb3ItZ2FtZS13aGF0LWlzLWl0KXt0YXJnZXQ9Il9ibGFuayJ9ICAKLSBTdHJlbmd0aGVuaW5nIGZhbWlseSBhbmQgY29tbXVuaXR5IGNvbm5lY3Rpb25zICAKLSBQcm9tb3RpbmcgYWNhZGVtaWMgYW5kIGNhcmVlciBlbmdhZ2VtZW50ICAKLSBMaWZlIHNraWxscyB0cmFpbmluZyBmb3IgeW91dGhzIGFuZCBmYW1pbGllcyAgCi0gRWR1Y2F0aW9uIGFib3V0IHN1YnN0YW5jZSBhYnVzZSAgCi0gW0NvZ25pdGl2ZSBiZWhhdmlvcmFsIHRoZXJhcHldKGh0dHBzOi8vd3d3LmFwYS5vcmcvcHRzZC1ndWlkZWxpbmUvcGF0aWVudHMtYW5kLWZhbWlsaWVzL2NvZ25pdGl2ZS1iZWhhdmlvcmFsKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIAoKClNlZSBbaGVyZV0oaHR0cHM6Ly95b3V0aC5nb3YvZXZpZGVuY2UtaW5ub3ZhdGlvbi9wcm9ncmFtLWRpcmVjdG9yeT9rZXl3b3Jkcz0mZmllbGRfcGRfZmFjdG9yc19yaXNrc190aWQ9NDEzJmZpZWxkX3BkX2ZhY3RvcnNfcHJvdGVjdGl2ZV90aWQ9QWxsKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCBbaGVyZV0oaHR0cHM6Ly9nb2MubWFyeWxhbmQuZ292L3dwLWNvbnRlbnQvdXBsb2Fkcy9zaXRlcy84LzIwMTUvMTAvUHJvZ3JhbS1Nb2RlbHMtZm9yLVNlcnZpbmctT3Bwb3J0dW5pdHktWW91dGgucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBsaXN0aW5ncyBvZiBwcm9ncmFtcyBkZWRpY2F0ZWQgdG8gcmVuZ2FnaW5nIGRpc2Nvbm5lY3RlZCB5b3V0aCBvciBwcmV2ZW50aW5nIGRpc2Nvbm5lY3Rpb24uCgpTZWUgW2hlcmVdKGh0dHBzOi8vd3d3LmNvbW11bml0aWVzdGhhdGNhcmUubmV0Lyl7dGFyZ2V0PSJfYmxhbmsifSBhbmQgCltoZXJlXShodHRwczovL2V4dGVuc2lvbi5wc3UuZWR1L3Byb21vdGluZy1zY2hvb2wtY29tbXVuaXR5LXVuaXZlcnNpdHktcGFydG5lcnNoaXBzLXRvLWVuaGFuY2UtcmVzaWxpZW5jZSl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgcGFydGljdWxhciBleGFtcGxlcy4KCgpUaGUgc3RhdGlzdGljcyB1c2VkIGluIHRoaXMgc2VjdGlvbiBjYW1lIGZyb20gdGhpcyBbYXJ0aWNsZV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNjI0MzQ0Ni8pe3RhcmdldD0iX2JsYW5rIn0uCgojIyAqKkxpbWl0YXRpb25zKioKKioqIAoKVGhlcmUgYXJlIHNvbWUgaW1wb3J0YW50IGNvbnNpZGVyYXRpb25zIHJlZ2FyZGluZyB0aGlzIGRhdGEgYW5hbHlzaXMgdG8ga2VlcCBpbiBtaW5kOiAKCjEpIFRoaXMgZGF0YSB1c2VkIGluIHRoZSBbTWVhc3VyZSBvZiBBbWVyaWNhXShodHRwczovL3d3dy5zc3JjLm9yZy9wcm9ncmFtcy92aWV3L21vYS8pe3RhcmdldD0iX2JsYW5rIn0gIHByb2plY3QgcmVwb3J0cyBmcm9tIHRoZSBpcyBkZXJpdmVkIGZyb20gW0FtZXJpY2FuIENvbW11bml0eSBTdXJ2ZXkoQVNDKV0oaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9wcm9ncmFtcy1zdXJ2ZXlzL2Fjcyl7dGFyZ2V0PSJfYmxhbmsifSB3aGljaCBleGNsdWRlcyBvciB1bmRlcnJlcHJlc2VudHMgY2VydGFpbiBvcHBvcnR1bml0eSB5b3V0aCBncm91cHMsIHN1Y2ggYXMgeW91dGhzIGluIHRoZSBqdXZlbmlsZSBqdXN0aWNlIHN5c3RlbSwgeW91dGhzIGluIHRoZSBmb3N0ZXIgY2FyZSBzeXN0ZW0sIGFuZCBob21lbGVzcyB5b3V0aHMgYXMgdGhlIHN1cnZleSBpcyBjb25kdWN0ZWQgb24gaG91c2Vob2xkcy4gRnVydGhlcm1vcmUsIHlvdXRocyB3aG8gbWF5IGJlIG1vcmUgZGlzY29ubmVjdGVkIGZvciBvdGhlciByZWFzb25zIGJlc2lkZXMgbm90IGJlaW5nIGluIHdvcmsgb3Igc2Nob29sLCBzdWNoIGFzIGRlYWxpbmcgd2l0aCB0aGUgYWRkZWQgY2hhbGxlbmdlIG9mIGJlaW5nIGEgdGVlbmFnZSBtb3RoZXIsIG9yIGJlaW5nIGFidXNlZCBpcyBub3QgYXZhaWxhYmxlIGluIHRoaXMgZGF0YXNldC4gVGh1cywgdGhpcyBkYXRhIGxpa2VseSB1bmRlcmVzdGltYXRlcyB5b3V0aCBkaXNjb25uZWN0aW9uIHJhdGVzLiAKCjIpIERhdGEgYWJvdXQgY2VydGFpbiBncm91cCBbaW50ZXJzZWN0aW9uc10oaHR0cHM6Ly93d3cudm94LmNvbS90aGUtaGlnaGxpZ2h0LzIwMTkvNS8yMC8xODU0Mjg0My9pbnRlcnNlY3Rpb25hbGl0eS1jb25zZXJ2YXRpc20tbGF3LXJhY2UtZ2VuZGVyLWRpc2NyaW1pbmF0aW9uKXt0YXJnZXQ9Il9ibGFuayJ9IChtZWFuaW5nIGZvciBleGFtcGxlIGluZGl2aWR1YWxzIG9mIGEgcGFydGljdWxhciBnZW5kZXIgYW5kIGV0aG5pY2l0eSkgb3IgcGFydGljdWxhciBncm91cHMgaW4gZ2VuZXJhbCBzdWNoIGFzIHNwZWNpZmljIGV0aG5pY2l0aWVzIG9yIGdlbmRlciBvciBzZXh1YWwgaWRlbnRpdHkgZ3JvdXBzIHN1Y2ggYXMgTEdCVCAobGVzYmlhbi9nYXkvYmlzZXh1YWwvdHJhbnNnZW5kZXIvcXVlZXIgYW5kIHF1ZXN0aW9uaW5nKSBvciBub25iaW5hcnkgZ2VuZGVyIHBvcHVsYXRpb25zIGlzIHVuZm9ydHVuYXRlbHkgbm90IGF2YWlsYWJsZSBpbiB0aGUgZGF0YSB1c2VkIGluIHRoaXMgYW5hbHlzaXMgYW5kIGluIG1vc3QgcmVzZWFyY2ggYWJvdXQgdGhpcyB0b3BpYy4gTHVja2lseSBob3dldmVyLCByZWNlbnQgeWVhcnMgb2YgdGhlIFtBQ1Mgc3VydmV5XShodHRwczovL3d3dy5jZW5zdXMuZ292L3Byb2dyYW1zLXN1cnZleXMvYWNzKXt0YXJnZXQ9Il9ibGFuayJ9IGhhcyBtb3JlIGRldGFpbGVkIGluZnJvbWF0aW9uIGFib3V0IGEgZ3JlYXRlciBudW1iZXIgb2YgcmFjaWFsIGFuZCBldGhuaWMgZ3JvdXBzIGFuZCByYWNpYWwvZXRobmljIGludGVyc2VjdGlvbnMuCgozKSBUaGUgc3RhdGlzdGljYWwgcHJvY2VkdXJlcyB3ZSBhcmUgdXNpbmcgbWF5IGJlIG92ZXJseSBzaW1wbGlzdGljLiAqSW4gYWxsIGRhdGEgYW5hbHlzaXMsIHdlIG5lZWQgdG8gYmUgd2FyeSBhYm91dCBkZXJpdmluZyBtZWFuaW5nIGZyb20gdGhlIHN0YXRpc3RpY2FsIHByb2NlZHVyZXMgd2UgdXNlKi4KCjQpIFVzaW5nIGltYWdlIHByb2Nlc3NpbmcgdG9vbHMgY2FuIGJlIHZlcnkgaGVscGZ1bC4gVGhlIG1hbm5lciBpbiB3aGljaCBkYXRhIGlzIG9idGFpbmVkIHdpdGggaW1hZ2UgcHJvY2Vzc2luZyB0b29scyBpcyB3aGF0IHdlIHdvdWxkIGRlc2NyaWJlIGFzIGEgKipibGFjayBib3ggcHJvY2VzcyoqLCA8dT4qYSBwcm9jZXNzIHdpdGgga25vd24gaW5wdXRzIGFuZCBvdXRwdXRzIGJ1dCB1bmtub3duIG1lY2hhbmljcyo8L3U+LiBCZWNhdXNlIHdlIGFyZSB1bmF3YXJlIG9mIGhvdyBvdXIgb3V0cHV0cyBhcmUgZ2VuZXJhdGVkIGZyb20gb3VyIGlucHV0cywgd2UgbmVlZCB0byBiZSB3YXJ5IG9mIHRoZSBvdXRwdXQuIFdpdGggdGhlIHNtYWxsIG91dHB1dCB3ZSBhcmUgY3JlYXRpbmcgaW4gdGhpcyBjYXNlIHN0dWR5LCBhIHZpc3VhbCBpbnNwZWN0aW9uIHNob3VsZCBzdWZmaWNlLiAKCgojIyAqKldoYXQgYXJlIHRoZSBkYXRhPyoqCioqKiAKCkluIHRoaXMgY2FzZSBzdHVkeSB3ZSB3aWxsIGJlIHVzaW5nIGRhdGEgcmVsYXRlZCB0byB5b3V0aCBkaXNjb25uZWN0aW9uIGZyb20gdGhlIHR3byBmb2xsb3dpbmcgcmVwb3J0cyBmcm9tIHRoZSBbTWVhc3VyZSBvZiBBbWVyaWNhXShodHRwczovL3d3dy5zc3JjLm9yZy9wcm9ncmFtcy92aWV3L21vYS8pe3RhcmdldD0iX2JsYW5rIn0gIHByb2plY3Q6Cgo+IE1lYXN1cmUgb2YgQW1lcmljYSBpcyBhIG5vbnBhcnRpc2FuIHByb2plY3Qgb2YgdGhlIG5vbnByb2ZpdCBbU29jaWFsIFNjaWVuY2UgUmVzZWFyY2ggQ291bmNpbF0oaHR0cHM6Ly93d3cuc3NyYy5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICBmb3VuZGVkIGluIDIwMDcgdG8gY3JlYXRlIGVhc3ktdG8tdXNlIHlldCBtZXRob2RvbG9naWNhbGx5IHNvdW5kIHRvb2xzIGZvciB1bmRlcnN0YW5kaW5nIHdlbGwtYmVpbmcgYW5kIG9wcG9ydHVuaXR5IGluIEFtZXJpY2EuIFRocm91Z2ggcmVwb3J0cywgaW50ZXJhY3RpdmUgYXBwcywgYW5kIGN1c3RvbS1idWlsdCBkYXNoYm9hcmRzLCBNZWFzdXJlIG9mIEFtZXJpY2Egd29ya3Mgd2l0aCBwYXJ0bmVycyB0byBicmVhdGhlIGxpZmUgaW50byBudW1iZXJzLCB1c2luZyBkYXRhIHRvIGlkZW50aWZ5IGFyZWFzIG9mIGhpZ2hlc3QgbmVlZCwgcGlucG9pbnQgbGV2ZXJzIGZvciBjaGFuZ2UsIGFuZCB0cmFjayBwcm9ncmVzcyBvdmVyIHRpbWUuCgoxLiBMZXdpcywgS3Jpc3Rlbi4gW01ha2luZyB0aGUgQ29ubmVjdGlvbjogVHJhbnNwb3J0YXRpb24gYW5kIFlvdXRoIERpc2Nvbm5lY3Rpb25dKGh0dHBzOi8vc3NyYy1zdGF0aWMuczMuYW1hem9uYXdzLmNvbS9tb2EvTWFraW5nJTIwdGhlJTIwQ29ubmVjdGlvbi5wZGYpe3RhcmdldD0iX2JsYW5rIn0gLiBOZXcgWW9yazogTWVhc3VyZSBvZiBBbWVyaWNhLCBTb2NpYWwgU2NpZW5jZSBSZXNlYXJjaCBDb3VuY2lsLCAyMDE5LiAgKERhdGEgdXAgdG8gMjAxNykKCmBgYHtyLCBvdXQud2lkdGg9IjQwMHB4IiwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiTWFraW5nX3RoZV9Db25uZWN0aW9uLnBuZyIpKQpgYGAKCjIuIDogTGV3aXMsIEtyaXN0ZW4uIFtBIERlY2FkZSBVbmRvbmU6IFlvdXRoIERpc2Nvbm5lY3Rpb24gaW4gdGhlIEFnZSBvZiBDb3JvbmF2aXJ1c10oaHR0cHM6Ly9zc3JjLXN0YXRpYy5zMy5hbWF6b25hd3MuY29tL21vYS9BRGVjYWRlVW5kb25lLnBkZil7dGFyZ2V0PSJfYmxhbmsifS4gTmV3IFlvcms6IE1lYXN1cmUgb2YgQW1lcmljYSwgU29jaWFsIFNjaWVuY2UgUmVzZWFyY2ggQ291bmNpbCwgMjAyMC4gKERhdGEgdXAgdG8gMjAxOCkKCmBgYHtyLCBvdXQud2lkdGg9IjQwMHB4IiwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiQV9EZWNhZGVfVW5kb25lLnBuZyIpKQpgYGAKClRoZSBkYXRhIHVzZWQgaW4gdGhlc2UgcmVwb3J0cyBjb21lcyBmcm9tIHRoZSBbQW1lcmljYW4gQ29tbXVuaXR5IFN1cnZleShBU0MpXShodHRwczovL3d3dy5jZW5zdXMuZ292L3Byb2dyYW1zLXN1cnZleXMvYWNzKXt0YXJnZXQ9Il9ibGFuayJ9LCB3aGljaCBpcyB0aGUgbGFyZ2VzdCBzdXJ2ZXkgY29uZHVjdGVkIGJ5IHRoZSBVbml0ZWQgU3RhdGVzIENlbnN1cyBCdXJlYXUuIFRoZSBzdXJ2ZXkgc3RhcnRlZCBpbiAyMDA1IGFuZCBjb2xsZWN0cyBkYXRhIGZvciAzLjUgbWlsbGlvbiBob3VzZWhvbGRzIGFubnVhbGx5LiBEYXRhIGlzIGNvbGxlY3RlZCBhYm91dCBhbmNlc3RyeSwgY2l0aXplaHNpcCwgaW5jb21lLCBlbXBsb3ltZW50LCBkaXNhYmlsaXR5IGFtb25nIG1hbnkgb3RoZXIgYXNwZWN0cy4gU2VlIFtoZXJlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9BbWVyaWNhbl9Db21tdW5pdHlfU3VydmV5KXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IHRoZSBzdXJ2ZXkuCgpBY2NvcmRpbmcgdG8gV2lraXBlZGlhIChodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9BbWVyaWNhbl9Db21tdW5pdHlfU3VydmV5KXt0YXJnZXQ9Il9ibGFuayJ9OgoKPiBEYXRhIGlzIGNvbGxlY3RlZCBieSBpbnRlcm5ldCwgbWFpbCwgdGVsZXBob25lIGludGVydmlld3MgYW5kIGluLXBlcnNvbiBpbnRlcnZpZXdzLi4uQWJvdXQgOTUgcGVyY2VudCBvZiBob3VzZWhvbGRzIGFjcm9zcyBhbGwgcmVzcG9uc2UgbW9kZXMgdWx0aW1hdGVseSByZXNwb25kLi4uIEFDUyByZXNwb25zZXMgYXJlIGNvbmZpZGVudGlhbC4uLiBhbmQgImltbXVuZSBmcm9tIGxlZ2FsIHByb2Nlc3MiCgo+IEl0IGlzIGEgbWFuZGF0b3J5IHN1cnZleSwgaXQgaXMgZ292ZXJuZWQgYnkgZmVkZXJhbCBsYXdzIHRoYXQgY291bGQgaW1wb3NlIGEgZmluZSBvZiBhcyBtdWNoIGFzICQ1LDAwMCBmb3IgcmVmdXNpbmcgdG8gcGFydGljaXBhdGUuCgoKIyMgKipEYXRhIEltcG9ydCoqCioqKiAKCk9uZSB3YXkgdG8gaW1wb3J0IGRhdGEgZnJvbSBhIHBkZiBpcyB0byB1c2UgdGhlICBgcGRmdG9vbHNgIHBhY2thZ2VzLiAKCkZyb20gdGhlIG91dHB1dCwgaXQncyBjbGVhciB0aGF0IGEgbGFyZ2UgYW1vdW50IG9mIG1hbmlwdWxhdGlvbiB3aWxsIGJlIHJlcXVpcmVkIHRvIHdyYW5nbGUgdGhpcyBkYXRhIHdpdGggdGhlIGBwZGZ0b29sc2AgcGFja2FnZS4KCiMjIyMgey5zY3JvbGxhYmxlIH0KYGBge3J9CnBkZl9kYXRhX2V4YW1wbGUgPC0gcGRmdG9vbHM6OnBkZl9kYXRhKGhlcmUoImRvY3MiLCAiTWFraW5nX3RoZV9Db25uZWN0aW9uLnBkZiIpKQoKdXRpbHM6OmhlYWQocGRmX2RhdGFfZXhhbXBsZSwgMSkKCnBkZl90b29sc19leGFtcGxlIDwtIHBkZnRvb2xzOjpwZGZfdGV4dChoZXJlKCJkb2NzIiwiTWFraW5nX3RoZV9Db25uZWN0aW9uLnBkZiIpKQoKaGVhZChwZGZfdG9vbHNfZXhhbXBsZSwgMSkKYGBgCiMjIyMKCldoaWxlIG5vdCBpbXBvc3NpYmxlLCBpdCdzIGhhcmQgbm90IHRvIGFyZ3VlIHRoYXQgdXNpbmcgdGhlIGBwZGZ0b29sc2AgcGFja2FnZSBpbiB0aGlzIHNjZW5hcmlvIHdpbGwgcmVxdWlyZSBhIGxvdCBvZiBhZHZhbmNlZCBkYXRhIHdyYW5nbGluZy4gV2hpbGUgb3VyIG91dHB1dCBtYXkgYmUgcmVwcm9kdWNpYmxlLCB0aGUgYW1vdW50IG9mIHRpbWUgdG8gYWNoaWV2ZSB0aGlzIHJlcHJvZHVjaWJpbGl0eSBtYXkgbm90IGJlIGFueSBtb3JlIGVmZmljaWVudCB0aGFuIHR5cGluZyB0aGUgdGFibGUgYnkgaGFuZCBpbnRvIGEgdGV4dCBvciBzcHJlYWRzaGVldCBwcm9ncmFtLgoKRm9ydHVuYXRlbHksIHRoZXJlIGlzIGFub3RoZXIgd2F5IHdlIGNhbiBwcm9jZWVkIHRvIHdyYW5nbGUgdGhlIGRhdGEuIAoKV2Ugd2lsbCBkZW1vbnN0cmF0ZSBob3cgdG8gcHJvZHVjZSByZXByb2R1Y2libGUgdGFibGVzIHdpdGggaW1hZ2UgcHJvY2Vzc2luZyBzb2Z0d2FyZSBpbiBgUmAuIAoKRm9yIGRlbW9uc3RyYXRpdmUgcHVycG9zZXMsIHdlIHdpbGwgaW1wb3J0IHR3byBzZXRzIG9mIGRhdGEuIFRoZSBmaXJzdCBzZXQgb2YgZGF0YSB3aWxsIGJlIHVzZWQgdG8gaGlnaGxpZ2h0IGNvbW1vbiBlcnJvcnMgdGhhdCB0aGUgaW1hZ2UgcHJvY2Vzc2luZyBzb2Z0d2FyZSBtYXkgcHJvZHVjZS4gVGhlIHNlY29uZCBzZXQgb2YgZGF0YSB3aWxsIGJlIHVzZWQgdG8gZGVtb25zdHJhdGUgaG93IHRvIGNpcmN1bXZlbnQgdGhlc2UgZXJyb3JzIGFuZCBwcm9kdWNlIHJlcHJvZHVjaWJsZSBkYXRhc2V0cyBlZmZpY2llbnRseS4KCldlIHdpbGwgbm93IGltcG9ydCB0aGUgZGF0YSB1c2luZyB0aGUgYG1hZ2lja2AgYW5kIGBoZXJlYCBwYWNrYWdlcy4gCgpgYGB7ciwgZHBpID0gMTAwMH0KI2JvbGQgaXMgY2F1c2luZyBpc3N1ZXMKaW1hZ2VfZXhhbXBsZSA8LSBtYWdpY2s6OmltYWdlX3JlYWQoaGVyZTo6aGVyZSgiaW1nIiwgImdlbmRlcl9yYWNlX2V0aG5pY2l0eS5wbmciKSkKCm1hZ2ljazo6aW1hZ2VfaW5mbyhpbWFnZV9leGFtcGxlKQpgYGAKCldlIGltcG9ydCB0aGUgc2FtZSBkYXRh4oCUdGhpcyB0aW1lIHdpdGhvdXQgcmVnaW9ucyBvZiB0aGUgdGFibGUgd2l0aG91dCBzcGVjaWFsIGZvcm1hdHRpbmfigJR1c2luZyB0aGUgYG1hZ2lja2AgYW5kIGBoZXJlYCBwYWNrYWdlcy4gCgpgYGB7ciwgZHBpID0gMTAwMH0KI2JvbGQgaXMgY2F1c2luZyBpc3N1ZXMKaW1hZ2UxIDwtIGltYWdlX3JlYWQoaGVyZSgiaW1nIiwgImdlbmRlcl9yYWNlX2V0aG5pY2l0eTIucG5nIikpCgptYWdpY2s6OmltYWdlX2luZm8oaW1hZ2UxKQpgYGAKCiMjICoqRGF0YSBFeHBsb3JhdGlvbiBhbmQgV3JhbmdsaW5nKioKKioqIAoKVGhlIGZpcnN0IGltYWdlIHdlIGltcG9ydGVkIGxvb2tzIGxpa2UgdGhpcy4gCgpgYGB7cn0KaW1hZ2VfZXhhbXBsZQpgYGAKClBhcnRzIG9mIHRoZSB0YWJsZSBkZXBpY3RlZCBpbiB0aGUgaW1hZ2UgYWJvdmUgY29udGFpbiBbKipuZXdsaW5lKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL05ld2xpbmU/b2xkZm9ybWF0PXRydWUpIGNoYXJhY3RlcnMuIEEgbmV3bGluZSBjaGFyYWN0ZXIgZGVub3RlcyB0aGUgZW5kIG9mIGEgbGluZSBvZiB0ZXh0IGFuZCB0aGUgc3RhcnQgb2YgYSBuZXcgbGluZSBvZiB0ZXh0LiAKClRoaXMgbWFrZXMgaXQgbW9yZSBkaWZmaWN1bHQgdG8gd3JhbmdsZSB0aGlzIHRhYmxlLiBXcmFuZ2xpbmcgdGhlIGRhdGEgdmlhIHJlZ3VsYXIgZXhwcmVzc2lvbnMgbWF5IGJlIHZlcnkgdGVkaW91cy4gSXQncyB1bmxpa2VseSB0aGF0IGltYWdlIHByb2Nlc3Npbmcgc29mdHdhcmUgY2FuIGhhbmRsZSB0aGUgbmV3bGluZSBjaGFyYWN0ZXJz4oCUb3IgYW55IG90aGVyIHNwZWNpYWwgY2hhcmFjdGVyc+KAlGNvcnJlY3RseS4KClVzaW5nIGBpbWFnZV9vY3IoKWAgYnkgYG1hZ2lja2Agb24gdGhlIGltYWdlIGFib3ZlIHdpbGwgcmVuZGVyIHNvbWUgZXJyb3JzIGluIHRoZSBmaXJzdCBmZXcgbGluZXMuIAoKYGBge3J9CmRmMSA8LSBtYWdpY2s6OmltYWdlX29jcihpbWFnZV9leGFtcGxlKQoKZGYxICU+JQogIGJhc2U6OnN0cnNwbGl0KCJcbiIpICU+JQogIGJhc2U6OnVubGlzdCgpICU+JQogIHRpYmJsZTo6YXNfdGliYmxlKCkKYGBgCgpJZiB3ZSByZW1vdmUgdGhlc2UgbGluZXMsIHNvbWUgbmV3IGVycm9ycyBlbWVyZ2UuIAoKYGBge3J9CmRmMSAlPiUKICBiYXNlOjpzdHJzcGxpdCgiXG4iKSAlPiUKICBiYXNlOjp1bmxpc3QoKSAlPiUKICB0aWJibGU6OmFzX3RpYmJsZSgpICU+JQogIGRwbHlyOjpzbGljZSgtKDE6MykpCmBgYAoKRGF0YSB3cmFuZ2xpbmcgaXMgbm90IGFuIGV4YWN0IHNjaWVuY2UuIFRoZSBhcHByb2FjaGVzIHdlIGNhbiB0YWtlIGFyZSBleHRyZW1lbHkgZGVwZW5kZW50IG9uIHRoZSBkYXRhLiBXZSBjYW4gZXhwbG9pdCBwYXR0ZXJucyBpbiB0aGUgZGF0YSB0byByZW5kZXIgdGhlIG91dHB1dCB3ZSBkZXNpcmUuIAoKV2Ugd2lsbCBub3cgdXNlIGEgY3JvcHBlZCB2ZXJzaW9uIG9mIHRoZSBpbWFnZSBhYm92ZSB3aXRob3V0IHRoZSBzcGVjaWFsIGZvcm1hdHRpbmcuCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyLCBkcGkgPSAxMDAwfQpybShkZjEpCgppbWFnZV9pbmZvKGltYWdlMSkKCmJhc2U6OnByaW50KGltYWdlMSkKCmRmMSA8LSBpbWFnZV9vY3IoaW1hZ2UxKQoKZGYxIDwtIGRmMSAlPiUKICBzdHJzcGxpdCgiXG4iKSAlPiUKICB1bmxpc3QoKSAlPiUKICBhc190aWJibGUoKQpgYGAKIyMjIwoKV2UgaGF2ZSBzZXZlcmFsIHN0cmluZ3MuIEVhY2ggY2VsbCBvZiBkYXRhIGlzIG9uIGEgc3RyaW5nIHNlcGFyYXRlZCBieSBzcGFjZS4gCgpXZSBzZXBhcmF0ZSBlYWNoIHN0cmluZyBieSBzcGFjZS4gCgpgYGB7cn0KZGYxIDwtIGRmMSAlPiUKICBkcGx5cjo6c2VsZWN0KHZhbHVlKSAlPiUKICBwdWxsKHZhbHVlKSAlPiUKICBzdHJfc3BsaXQoIiAiKQpgYGAKCldlIHNwbGl0IHRoZSBkYXRhZnJhbWUgaW4gdHdvOiBhIGxhYmVscyBzZWN0aW9uIGFuZCBhICJkYXRhIiBzZWN0aW9uIGNvbnRhaW5pbmcgdGhlIGluZm9ybWF0aW9uIHdlIGFyZSBpbnRlcmVzdGVkIGluLiAKCkluIHRoZSBmaXJzdCBoYWxmLCB3ZSByZW1vdmUgYWxsIGRpZ2l0cyBhbmQgcHVuY3R1YXRpb24gdG8gZW5zdXJlIHRoYXQgd2UgYXJlIGxlZnQgd2l0aCBjaGFyYWN0ZXIgbGFiZWxzLgoKSW4gdGhlIHNlY29uZC1oYWxmLCByZW1vdmUgY29tbWFzIGFuZCBwZXJpb2RzLCBjb252ZXJ0aW5nIHRoZSByZXN1bHRpbmcgc3RyaW5nIGNoYXJhY3RlciBjbGFzcyB0byBudW1lcmljIGFuZCBzZWxlY3RpdmVseSBtdWx0aXBseWluZyBjb2x1bW5zIHRvIHJlaW50cm9kdWNlIHRoZSBkZWNpbWFsIHBvaW50IGNvcnJlY3RseSAKCmBgYHtyfQpkZjFhIDwtIGRmMSAlPiUKICBwdXJycjo6bWFwKH5iYXNlOjpwYXN0ZSguLGNvbGxhcHNlID0gIiIpKSAlPiUKICBwdXJycjo6bWFwKH5iYXNlOjpnc3ViKCJbWzpkaWdpdDpdXSt8W1s6cHVuY3Q6XV0rIiwgIiIsLikpICU+JQogIGJhc2U6OmRvLmNhbGwoYmFzZTo6cmJpbmQsLikgJT4lCiAgYmFzZTo6ZGF0YS5mcmFtZSgpICU+JQogIGRwbHlyOjp0aWJibGUoKQoKZGYxYiA8LSBtYXAoZGYxLCB0YWlsLCA4KSAlPiUKICBtYXAofmdzdWIoIlssXSt8Wy5dKyIsICIiLC4pKSAlPiUKICBkby5jYWxsKHJiaW5kLC4pICU+JQogIGRhdGEuZnJhbWUoKSAlPiUKICBkcGx5cjo6bXV0YXRlX2lmKGJhc2U6OmlzLmNoYXJhY3RlciwgYmFzZTo6YXMubnVtZXJpYykgJT4lCiAgZHBseXI6Om11dGF0ZV9hdCh2YXJzKC1YNyksIH4gLiAqIDAuMSkgJT4lCiAgdGliYmxlKCkgCgpiYXNlOjpybShkZjEpCmBgYAoKV2UgY29tYmluZSB0aGUgdHdvIHNlY3Rpb25zIG9mIGRhdGEgdG8gY3JlYXRlIG91ciBkYXRhZnJhbWUsIHJlbW92aW5nIGFuZCB0aGVuIGFkZGluZyBjb2x1bW4gbmFtZXMuCgpgYGB7cn0KZGYxIDwtIGRwbHlyOjpiaW5kX2NvbHMoZGYxYSwKICAgICAgICAgICAgICAgICAgICAgICAgZGYxYikKCmJhc2U6Om5hbWVzKGRmMSkgPC0gYygpCgpjb2x1bW5fbmFtZXMgPC0gYygiR3JvdXAiLAogICAgICAgICAgICAgICAgICAiUGVyY18yMDA4IiwKICAgICAgICAgICAgICAgICAgIlBlcmNfMjAxMCIsCiAgICAgICAgICAgICAgICAgICJQZXJjXzIwMTIiLAogICAgICAgICAgICAgICAgICAiUGVyY18yMDE0IiwKICAgICAgICAgICAgICAgICAgIlBlcmNfMjAxNiIsCiAgICAgICAgICAgICAgICAgICJQZXJjXzIwMTciLAogICAgICAgICAgICAgICAgICAiTl8yMDE3IiwKICAgICAgICAgICAgICAgICAgIkRlbHRhX3BlcmMiKQoKYmFzZTo6Y29sbmFtZXMoZGYxKSA8LSBjb2x1bW5fbmFtZXMKYGBgCgpXZSByZW1vdmUgY29sdW1ucyB3aXRoIGluZm9ybWF0aW9uIHdlIGRvbid0IG5lZWQgYW5kIHVzZSB0aGUgY29tbW1vbiBwYXR0ZXJuIGluIHRoZSBjb2x1bW4gbmFtZXMgdG8gY29udmVydCB0aGUgZGF0YSBpbnRvIFtsb25nL25hcnJvdyBmb3JtYXRdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dpZGVfYW5kX25hcnJvd19kYXRhP29sZGZvcm1hdD10cnVlKS4KCmBgYHtyfQpkZjEgPC0gZGYxICU+JQogIGRwbHlyOjpzZWxlY3QoLU5fMjAxNywKICAgICAgICAgICAgICAgIC1EZWx0YV9wZXJjKQoKZGYxIDwtIGRmMSAlPiUKICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGNvbHM9Y29udGFpbnMoIlBlcmNfIiksCiAgICAgICAgICAgICAgICAgICAgICBuYW1lc190byA9ICJZZWFyIiwKICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJSYXRlIiwKICAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3ByZWZpeCA9ICJQZXJjXyIpICU+JQogIGRwbHlyOjptdXRhdGUoWWVhciA9IGFzLm51bWVyaWMoWWVhcikpCmBgYAoKV2UgdXNlIHRoZSBgZHBseXI6OmNhc2Vfd2hlbigpYCBhbmQgYHN0cmluZ3I6OnN0cl9kZXRlY3QoKWAgZnVuY3Rpb24gdG8gZGV0ZWN0IHBhdHRlcm5zIGFuZCBjcmVhdGUgYW4gc2VwYXJhdGUgY29sdW1uIHdpdGggZ2VuZGVyIGFuZCByYWNlIGluZm9ybWF0aW9uLgoKVGhlIHR3byBjb2x1bW5zIGNyZWF0ZWQgY29udGFpbiBgVFJVRS9GQUxTRWAgc3RhdGVtZW50cy4gVGhlc2UgYXJlIHRoZW4gdXNlZCB0byBjcmVhdGUgYSB0aGlyZCBjb2x1bW4gdGhhdCB3aWxsIGFsbG93IHVzIHRvIHNlcGFyYXRlIHRoZSBkYXRhIGJ5IGl0cyBzdW1tYXJ5IGxldmVsLiAKCmBgYHtyfQpkZjEgPC0gZGYxICU+JQogIG11dGF0ZShHZW5kZXIgPSBkcGx5cjo6Y2FzZV93aGVuKHN0cmluZ3I6OnN0cl9kZXRlY3QoR3JvdXAsICJGZW1hbGUiKSB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KEdyb3VwLCAiTWFsZSIpIH4gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gTkEpLAogICAgICAgICBSYWNlID0gc3RyaW5ncjo6c3RyX3JlbW92ZV9hbGwoR3JvdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gcGFzdGUoYygiRmVtYWxlIiwiTWFsZSIsIlVuaXRlZFN0YXRlcyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gInwiKSkpICU+JQogIG11dGF0ZShSYWNlID0gZHBseXI6Om5hX2lmKFJhY2UsICIiKSkKCmRmMSA8LSBkZjEgJT4lIAogIG11dGF0ZShUeXBlID0gY2FzZV93aGVuKGJhc2U6OmlzLm5hKEdlbmRlcikgJiBiYXNlOjppcy5uYShSYWNlKSB+ICJVUyBUb3RhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYmFzZTo6aXMubmEoR2VuZGVyKSAmICFiYXNlOjppcy5uYShSYWNlKSB+ICJSYWNlIFRvdGFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAhYmFzZTo6aXMubmEoR2VuZGVyKSAmIGJhc2U6OmlzLm5hKFJhY2UpIH4gIkdlbmRlciBUb3RhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJTdWJncm91cCBUb3RhbCIpKQoKZGYxIDwtIGRmMSAlPiUKICBtdXRhdGUoR2VuZGVyID0gY2FzZV93aGVuKHN0cl9kZXRlY3QoR3JvdXAsICJGZW1hbGUiKSB+ICJGZW1hbGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChHcm91cCwgIk1hbGUiKSB+ICJNYWxlIikpCmBgYAoKVGhlIGNvbHVtbnMgb2YgYGNoYXJhY3RlcmAgY2xhc3MgY3VycmVudGx5IGNvbnRhaW4gdXBwZXIgYW5kIGxvd2VyIGNhc2UgY2hhcmFjdGVycy4gV2Ugd2FudCB0byBlbnN1cmUgdGhhdCB3ZSB1c2UgYSBjYXNlcyBjb25zaXN0ZW50bHkgdG8gZW5zdXJlIHRoYXQgdGhlcmUgYXJlIG5vIGVycm9ycyBkcml2ZW4gYnkgY2FzZS1zZW5zaXRpdmUgZnVuY3Rpb24gZG93bnN0cmVhbS4KClRvIGRvIHRoaXMsIHdlIHVzZSB0aGUgYGJhc2U6OnRvX3VwcGVyKClgIGZ1bmN0aW9uLiBUaGlzIGZ1bmN0aW9uIG1ha2VzIGFsbCBjaGFyYWN0ZXJzIHVwcGVyY2FzZS4KCmBgYHtyfQpkZjEgPC0gZGYxICU+JSAKICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCB0b3VwcGVyKQpgYGAKCkZpbmFsbHksIHdlIGhvbW9nZW5pemUgdGhlIGxhYmVscyBhc3NpZ25lZCBmb3IgY2VydGFpbiBncm91cHMsIGZpbGwgaW4gbWlzc2luZyAoYE5BYCkgdmFsdWVzIHdpdGggYSBzdHJpbmcsIGFuZCByZW1vdmUgY29sdW1ucyB3ZSBubyBsb25nZXIgbmVlZCBmcm9tIHRoZSBkYXRhZnJhbWUuIAoKYGBge3J9CmRmMSA8LSBkZjEgJT4lCiAgbXV0YXRlKFJhY2UgPSBjYXNlX3doZW4oUmFjZSA9PSAiTEFUSU5BIiB+ICJMQVRJTk8vQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgUmFjZSA9PSAiTEFUSU5PIiB+ICJMQVRJTk8vQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgUmFjZSA9PSAiTkFUSVZFQU1FUklDQU4iIH4gIk5BVElWRSBBTUVSSUNBTiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IFJhY2UpKSAlPiUKICBtdXRhdGUoR2VuZGVyID0gdGlkeXI6OnJlcGxhY2VfbmEoR2VuZGVyLCAiQUxMIiksCiAgICAgICAgIFJhY2UgPSB0aWR5cjo6cmVwbGFjZV9uYShSYWNlLCAiQUxMIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUdyb3VwKQpgYGAKCldlIGNhbiByZXBlYXQgdGhpcyBwcm9jZXNzIGZvciB0aGUgb3RoZXIgdHdvIHRhYmxlcyBsaXN0ZWQgb24gcGFnZSAzOS4KCkxldCdzIGxvb2sgYXQgdGhlIHRhYmxlIHdpdGhvdXQgdGhlIHNwZWNpYWwgZm9ybWF0dGluZy4KCmBgYHtyfQppbWFnZTIgPC0gaW1hZ2VfcmVhZChoZXJlKCJpbWciLCAiYXNpYW5fc3ViZ3JvdXBzLnBuZyIpKQppbWFnZTIKYGBgCgpBcyB5b3UgY2FuIHNlZSwgdGhlcmUgYXJlIGVtcHR5IHNwYWNlcy4gQWNjb3JkaW5nIHRvIHRoZSBQREYsIHRoZXNlIHNwYWNlcyBhcmUgZW1wdHkgdG8gZGVub3RlIHRoYXQgdGhlIGVzdGltYXRlcyBhcmUgdW5yZWxpYWJsZS4KClRoaXMgbWF5IGNhdXNlIHByb2JsZW1zLiBXaGl0ZXNwYWNlIG11c3QgYmUgaGFuZGxlZCBkaWZmZXJlbnRseS4gV2UgbWF5IG5vdCB3YW50IHRvIHByb2Nlc3MgdGhlIGVudGlyZSBpbWFnZSBmb3IgdGhpcyByZWFzb24uIAoKSW5zdGVhZCwgd2UgY2FuIHVzZSBzZXBhcmF0ZSBpbWFnZXMgdG8gZW5zdXJlIGEgc2ltcGxlciBwcm9jZXNzIGxpa2UgdGhhdCBhYm92ZS4gCgpXZSByZWFkIHRoZSB0aHJlZSBpbWFnZXMuIApgYGB7cn0KaW1hZ2UyYSA8LSBpbWFnZV9yZWFkKGhlcmUoImltZyIsICJhc2lhbl9zdWJncm91cHNBLnBuZyIpKQppbWFnZTJiIDwtIGltYWdlX3JlYWQoaGVyZSgiaW1nIiwgImFzaWFuX3N1Ymdyb3Vwc0IucG5nIikpCmltYWdlMmMgPC0gaW1hZ2VfcmVhZChoZXJlKCJpbWciLCAiYXNpYW5fc3ViZ3JvdXBzQy5wbmciKSkKCm1hZ2ljazo6aW1hZ2VfaW5mbyhpbWFnZTJhKQptYWdpY2s6OmltYWdlX2luZm8oaW1hZ2UyYikKbWFnaWNrOjppbWFnZV9pbmZvKGltYWdlMmMpCmBgYAoKVGhlIGltYWdlcyBsb29rIGxpa2UgdGhpcy4KCmBgYHtyfQppbWFnZTJhCmltYWdlMmIKaW1hZ2UyYwpgYGAKCldlIHNhdmUgdGhlIHRleHQgZnJvbSB0aGUgaW1hZ2VzIGludG8gb2JqZWN0cy4KCmBgYHtyfQpkZjJhIDwtIG1hZ2ljazo6aW1hZ2Vfb2NyKGltYWdlMmEpCmRmMmIgPC0gbWFnaWNrOjppbWFnZV9vY3IoaW1hZ2UyYikKZGYyYyA8LSBtYWdpY2s6OmltYWdlX29jcihpbWFnZTJjKQpgYGAKCldlIHByb2Nlc3MgdGhlc2Ugb2JqZWN0cyBzZXBhcmF0ZWx5LiBOb3RlIHRoYXQgd2UgdXNlIGEgdmVyeSBzaW1pbGFyIHByb2Nlc3MgdG8gdGhhdCBlbXBsb3llZCBpbiB0aGUgd3JhbmdsaW5nIG9mIHRoZSBwcmV2aW91cyB0YWJsZS4gCgpgYGB7cn0KZGYyYSA8LSBkZjJhICU+JQogIHN0cnNwbGl0KCJcbiIpICU+JQogIHVubGlzdCgpICU+JQogIGFzX3RpYmJsZSgpCgpkZjJiIDwtIGRmMmIgJT4lCiAgc3Ryc3BsaXQoIlxuIikgJT4lCiAgdW5saXN0KCkgJT4lCiAgYXNfdGliYmxlKCkKCmRmMmMgPC0gZGYyYyAlPiUKICBzdHJzcGxpdCgiXG4iKSAlPiUKICB1bmxpc3QoKSAlPiUKICBhc190aWJibGUoKQpgYGAKCldlIHRoZW4gY29tYmluZSB0aGUgb2JqZWN0cyB3aXRoIHRoZSBgZHBseXI6OmJpbmRfcm93cygpYCBmdW5jdGlvbi4KClRoZSBwcm9jZXNzIGlzIG5vdyB2ZXJ5IHNpbWlsYXIgdG8gdGhlIHByZXZpb3VzIHRhYmxlLgoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojZmZjY2NiOyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKk1JQ0hBRUwgT05USVZFUk9TKioKCipJIHVzZWQgYmFzZSBSIHRvIHJlbW92ZSB0aGUgZmlyc3QgdGhyZWUgcm93cyBvZiBhIGRhdGFmcmFtZSBpbiB0aGUgZm9sbG93aW5nIGNodW5rLiBJIGFtIG5vdCBhd2FyZSBvZiBhIHRpZHl2ZXJzZSBzb2x1dGlvbiBmb3IgdGhpczsgSSBhbSBzdXJlIG9uZSBleGlzdHMuKgo8L2Rpdj4KCmBgYHtyfQpkZjIgPC0gYmluZF9yb3dzKGRmMmEsCiAgICAgICAgICBkZjJiLAogICAgICAgICAgZGYyYykKCmRmMiA8LSBkZjIgJT4lCiAgZHBseXI6OnNlbGVjdCh2YWx1ZSkgJT4lCiAgcHVsbCh2YWx1ZSkgJT4lCiAgc3RyX3NwbGl0KCIgIikKCmRmMmIgPC0gbWFwKGRmMiwgdGFpbCwgMikgJT4lCiAgbWFwKH5nc3ViKCJbLF0rfFsuXSsiLCAiIiwuKSkgJT4lCiAgZG8uY2FsbChyYmluZCwuKSAlPiUKICBkYXRhLmZyYW1lKCkgJT4lCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMubnVtZXJpYykgJT4lCiAgbXV0YXRlX2F0KHZhcnMoLVgyKSwgfiAuICogMC4xKSAlPiUKICB0aWJibGUoKSAKCmRmMmEgPC0gZGYyICU+JQogIG1hcCh+cGFzdGUoLixjb2xsYXBzZSA9ICIiKSkgJT4lCiAgbWFwKH5nc3ViKCJbWzpkaWdpdDpdXSt8W1s6cHVuY3Q6XV0rIiwgIiIsLikpICU+JQogIGRvLmNhbGwocmJpbmQsLikgJT4lCiAgZGF0YS5mcmFtZSgpICU+JQogIHRpYmJsZSgpCgpkZjIgPC0gYmluZF9jb2xzKGRmMmEsIGRmMmIpCgpuYW1lcyhkZjIpIDwtIGMoKQoKY29sdW1uX25hbWVzIDwtIGMoIkdyb3VwIiwKICAgICAgICAgICAgICAgICAgIlJhdGUiLAogICAgICAgICAgICAgICAgICAiTl8yMDE3IikKCmNvbG5hbWVzKGRmMikgPC0gY29sdW1uX25hbWVzCgpkZjIgPC0gZGYyICU+JQogIGRwbHlyOjpzZWxlY3QoLU5fMjAxNykKCmRmMiA8LSBkZjIgJT4lCiAgZHBseXI6Om11dGF0ZShZZWFyID0gMjAxNykKCmRmMiA8LSBkZjIgJT4lCiAgbXV0YXRlKEdlbmRlciA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KEdyb3VwLCAiRmVtYWxlIikgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChHcm91cCwgIk1hbGUiKSB+IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BKSwKICAgICAgICAgU3ViZ3JvdXAgPSBzdHJfcmVtb3ZlX2FsbChHcm91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gcGFzdGUoYygiRmVtYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWFsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFTSUFOIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXNpYW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICJ8IikpKSAlPiUKICBtdXRhdGUoU3ViZ3JvdXAgPSBuYV9pZihTdWJncm91cCwgIiIpKQoKZ2xpbXBzZShkZjIpCgpkZjIgPC0gZGYyWy0oMTozKSxdCgpkZjIgPC0gZGYyICU+JSAKICBtdXRhdGUoVHlwZSA9IGNhc2Vfd2hlbihpcy5uYShHZW5kZXIpICYgaXMubmEoU3ViZ3JvdXApIH4gIkFzaWFuIFRvdGFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShHZW5kZXIpICYgIWlzLm5hKFN1Ymdyb3VwKSB+ICJTdWJncm91cCBUb3RhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKEdlbmRlcikgJiBpcy5uYShTdWJncm91cCkgfiAiR2VuZGVyIFRvdGFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIlN1Ymdyb3VwIFRvdGFsIikpCgpnbGltcHNlKGRmMikKCmRmMiA8LSBkZjIgJT4lCiAgbXV0YXRlKEdlbmRlciA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KEdyb3VwLCAiRmVtYWxlIikgfiAiRmVtYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoR3JvdXAsICJNYWxlIikgfiAiTWFsZSIpKQoKZGYyIDwtIGRmMiAlPiUgCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgdG9sb3dlcikgJT4lCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgdG91cHBlcikKCmRmMiA8LSBkZjIgJT4lCiAgbXV0YXRlKEdlbmRlciA9IHJlcGxhY2VfbmEoR2VuZGVyLCAiQUxMIiksCiAgICAgICAgIFN1Ymdyb3VwID0gcmVwbGFjZV9uYShTdWJncm91cCwgIkFMTCIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1Hcm91cCkgJT4lCiAgbXV0YXRlKFN1Ymdyb3VwKQoKZGYyIDwtIGRmMiAlPiUKICBtdXRhdGUoU3ViZ3JvdXAgPSBjYXNlX3doZW4oU3ViZ3JvdXAgPT0gIlRXT09STU9SRSIgfiAiVFdPIE9SIE1PUkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gU3ViZ3JvdXApKQpgYGAKCk5vdGUgdGhhdCB3ZSB0b29rIGEgcHJvY2VzcyB0aGF0IGhhZCBzdWNjZXNzZnVsbHkgd29ya2VkIGZvciB1cyBhbmQgbW9kaWZpZWQgaXQgc2xpZ2h0bHkgZm9yIHNlcGFyYXRlLCBzaW1pbGFybHktc291cmNlZCBkYXRhLiAKClRoaXMgaXMgYSBjb21tb24gYXBwcm9hY2ggaW4gZGF0YSBzY2llbmNlLiBPZnRlbiwgdGhlIGR1cmF0aW9uIG9mIHRoZSB3cmFuZ2xpbmcgcHJvY2VzcyBjYW4gbGltaXQgdGhlIGRlcHRoIG9mIGFuIGFuYWx5c2lzIGZvciBwcmFjdGljYWwgcmVhc29ucy4gVXNpbmcgdHJpZWQgbWV0aG9kcyBjYW4gaGVscCByZWR1Y2UgdGhlIHRpbWUgbmVlZGVkIHRvIHdyYW5nbGUgZGF0YSBhbmQgYWxsb3cgdGltZSBmb3Igb3RoZXIgcGFydHMgb2YgYW4gYW5hbHlzaXMuIAoKTGV0J3MgYWRkIHRoZSAyMDE4IGRhdGEgZm9yIHRoaXMgZ3JvdXAuCgpXZSBpbXBvcnQgdGhlIGltYWdlLiAKCmBgYHtyfQppbWFnZTUgPC0gaW1hZ2VfcmVhZChoZXJlKCJpbWciLCAiYXNpYW5fc3ViZ3JvdXBzXzIwMTgucG5nIikpCgpkZjJfMjAxOCA8LSBtYWdpY2s6OmltYWdlX29jcihpbWFnZTUpCmBgYAoKQXMgeW91IGNhbiBzZWUsIHdlIGhhdmUgcmVwZWF0ZWQgbmV3bGluZXMgKGBcbmApLiBXZSBjYW4gcmVtb3ZlIHRoZXNlIHdpdGggc29tZSBzaW1wbGV4IHJlZ2V4LgoKYGBge3J9CmRmMl8yMDE4IDwtIGdzdWIoJyhbXG5dKVxcMSsnLAogICAgICAgICAgICAgICAgICdcXDEnLAogICAgICAgICAgICAgICAgIGRmMl8yMDE4KQoKZGYyXzIwMTggPC0gZ3N1YigiW1s6cHVuY3Q6XV0rIiwKICAgICAgICAgICAgICAgICAiIiwKICAgICAgICAgICAgICAgICBkZjJfMjAxOCkKCmRmMl8yMDE4IDwtIGdzdWIoIiBpICIsCiAgICAgICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICAgICAgZGYyXzIwMTgpCmBgYAoKV2UgcHJvY2VlZCwgbWFraW5nIHNsaWdodCBtb2RpZmljYXRpb25zIHRvIHRoZSBwcm9jZXNzIGFzIG5lZWRlZC4KClRoZSBib2xkIGZvbnQgYXBwZWFycyB0byBoYXZlIGNhdXNlZCBhIHR5cG9zLiAKCmBgYHtyfQpkZjJfMjAxOCAlPiUKICBzdHJzcGxpdCgiXG4iKSAlPiUKICB1bmxpc3QoKSAlPiUKICBhc190aWJibGUoKQpgYGAKCldlIGZpeCB0aGUgdHlwb3MuCgpgYGB7cn0KZGYyXzIwMTggPC0gZGYyXzIwMTggJT4lCiAgc3Ryc3BsaXQoIlxuIikgJT4lCiAgdW5saXN0KCkgJT4lCiAgZ3N1YigiIEI0NCAiLCI1NCIsLikgJT4lCiAgZ3N1YigiV29tZW43NCIsIldvbWVuIDc0IiwuKSAlPiUKICBnc3ViKCJITU9ORzEwMiIsIkhNT05HIDEwMiIsLikgJT4lCiAgYXNfdGliYmxlKCkKCmRmMl8yMDE4ICU+JQogIHByaW50KC4sbiA9IGRpbSguKVsxXSkKYGBgCgpXZSB0aGVuIGNvbnRpbnVlIGFzIHdlIHdvdWxkIG5vcm1hbGx5LiAKCmBgYHtyfQpkZjJfMjAxOCA8LSBkZjJfMjAxOCAlPiUKICBkcGx5cjo6c2VsZWN0KHZhbHVlKSAlPiUKICBwdWxsKHZhbHVlKSAlPiUKICBzdHJfc3BsaXQoIiAiKQoKZGYyXzIwMTggPC0gbGFwcGx5KGRmMl8yMDE4LAogICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkgeFtuY2hhcih4KSA+PSAxXSkKCmRmMmFfMjAxOCA8LSBkZjJfMjAxOCAlPiUKICBtYXAofnBhc3RlKC4sY29sbGFwc2UgPSAiIikpICU+JQogIG1hcCh+Z3N1YigiW1s6ZGlnaXQ6XV0rfFtbOnB1bmN0Ol1dKyIsICIiLC4pKSAlPiUKICBkby5jYWxsKHJiaW5kLC4pICU+JQogIGRhdGEuZnJhbWUoKSAlPiUKICB0aWJibGUoKQoKZGYyYl8yMDE4IDwtIG1hcChkZjJfMjAxOCwgdGFpbCwgMikgJT4lCiAgZG8uY2FsbChyYmluZCwuKSAlPiUKICBkYXRhLmZyYW1lKCkgJT4lCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMubnVtZXJpYykgJT4lCiAgbXV0YXRlX2F0KHZhcnMoLVgyKSwgfiAuICogMC4xKSAlPiUKICB0aWJibGUoKSAKCnJtKGRmMl8yMDE4KQogIApkZjJfMjAxOCA8LSBiaW5kX2NvbHMoZGYyYV8yMDE4LAogICAgICAgICAgICAgICAgICAgICAgZGYyYl8yMDE4KQpuYW1lcyhkZjJfMjAxOCkgPC0gYygpCgpjb2x1bW5fbmFtZXMgPC0gYygiR3JvdXAiLAogICAgICAgICAgICAgICAgICAiUmF0ZSIsCiAgICAgICAgICAgICAgICAgICJOXzIwMTciKQoKY29sbmFtZXMoZGYyXzIwMTgpIDwtIGNvbHVtbl9uYW1lcwoKZGYyXzIwMTggPC0gZGYyXzIwMTggJT4lCiAgZHBseXI6OnNlbGVjdCgtTl8yMDE3KQoKZGYyXzIwMTggPC0gZGYyXzIwMTggJT4lCiAgZHBseXI6Om11dGF0ZShZZWFyID0gMjAxOCkKCmRmMl8yMDE4IDwtIGRmMl8yMDE4ICU+JQogIG11dGF0ZShHZW5kZXIgPSBjYXNlX3doZW4oc3RyX2RldGVjdChHcm91cCwgIldvbWVuIikgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChHcm91cCwgIk1lbiIpIH4gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gTkEpKQoKbGFiZWxzIDwtIHVubGlzdChkZjJfMjAxOFtjKHNlcSgxLDE1LCBieT0zKSwxNiwxNyksMV0sIHVzZS5uYW1lcyA9IEZBTFNFKQoKZGltKGRmMl8yMDE4KVsxXQoKbGFiZWxzXzMgPC0gYyhyZXAobGFiZWxzWzE6NV0sIGVhY2ggPSBkaW0oZGYyXzIwMTgpWzFdLyhsZW5ndGgobGFiZWxzKS0yKSksCiAgICAgICAgICAgICAgIkhNT05HIiwKICAgICAgICAgICAgICAiQ0FNQk9ESUFOIikKCmRmMl8yMDE4JFN1Ymdyb3VwIDwtIGxhYmVsc18zCgpkZjJfMjAxOCA8LSBkZjJfMjAxOCAlPiUgCiAgbXV0YXRlKFR5cGUgPSAiU3ViZ3JvdXAgVG90YWwiKQoKZ2xpbXBzZShkZjJfMjAxOCkKCmRmMl8yMDE4IDwtIGRmMl8yMDE4ICU+JQogIG11dGF0ZShHZW5kZXIgPSBjYXNlX3doZW4oR2VuZGVyID09IFRSVUUgfiAiRmVtYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdlbmRlciA9PSBGQUxTRSB+ICJNYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiQWxsIikpCgpkZjJfMjAxOCA8LSBkZjJfMjAxOCAlPiUgCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgdG9sb3dlcikgJT4lCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgdG91cHBlcikKCmRmMl8yMDE4IDwtIGRmMl8yMDE4ICU+JQogIGRwbHlyOjpzZWxlY3QoLUdyb3VwKQpgYGAKClRoZSBkYXRhZnJhbWUgd2UgcHJvZHVjZWQgZG9lcyBub3QgY29udGFpbiB0b3RhbHMuIAoKYGBge3J9CmRmMl8yMDE4ICU+JQogIHByaW50KC4sIG4gPSBkaW0oLilbMV0pCmBgYAoKV2UgY2FuIGZpbmQgdGhlc2UgdG90YWxzIGluIHRoZSBQREYgZGlyZWN0bHkgYW5kIGNyZWF0ZSByb3dzIGFzIG5lZWRlZAoKV2UgbG9hZCB0aGUgUERGLgoKYGBge3J9CmV4Y2VycHQgPC0gaW1hZ2VfcmVhZChoZXJlKCJpbWciLCAiYXNpYW5feW91dGhfZXhjZXJwdC5wbmciKSkKCmV4Y2VycHQKYGBgCgpXZSBhZGQgdGhlIHJvd3MuCgpgYGB7cn0KZGYyXzIwMTggPC0gZGYyXzIwMTggJT4lCiAgYWRkX3JvdyhSYXRlID0gNi4yLAogICAgICAgICAgWWVhciA9IDIwMTgsCiAgICAgICAgICBHZW5kZXIgPSAiQUxMIiwKICAgICAgICAgIFN1Ymdyb3VwID0gIkFMTCIsIAogICAgICAgICAgVHlwZSA9ICJBU0lBTiBUT1RBTCIpICU+JQogIGFkZF9yb3coUmF0ZSA9IDYuMSwKICAgICAgICAgIFllYXIgPSAyMDE4LAogICAgICAgICAgR2VuZGVyID0gIkZFTUFMRSIsCiAgICAgICAgICBTdWJncm91cCA9ICJBTEwiLCAKICAgICAgICAgIFR5cGUgPSAiR0VOREVSIFRPVEFMIikgJT4lCiAgYWRkX3JvdyhSYXRlID0gNi40LAogICAgICAgICAgWWVhciA9IDIwMTgsCiAgICAgICAgICBHZW5kZXIgPSAiTUFMRSIsCiAgICAgICAgICBTdWJncm91cCA9ICJBTEwiLCAKICAgICAgICAgIFR5cGUgPSAiR0VOREVSIFRPVEFMIikKYGBgCgpgYGB7cn0KZGYyIDwtIGJpbmRfcm93cyhkZjIsCiAgICAgICAgICAgICAgICAgZGYyXzIwMTgpCmBgYAoKV2UgcmVwZWF0IHRoaXMgcHJvY2VzcyBhZ2FpbiBmb3IgTGF0aW5vL2Egc3ViZ3JvdXBzLiAKClRoZSB0YWJsZSwgd2l0aG91dCB0aGUgc3BlY2lhbCBmb3JtYXR0aW5nLCBsb29rcyBsaWtlIHRoaXMuCgpgYGB7cn0KaW1hZ2UzIDwtIGltYWdlX3JlYWQoaGVyZSgiaW1nIiwgImxhdGlub19hX3N1Ymdyb3Vwcy5wbmciKSkKYGBgCgpUaGVyZSBhcmUgbm8gd2hpdGVzcGFjZXMgaW4gdGhpcyB0YWJsZS4KCldlIHByb2NlZWQgdXNpbmcgd2hhdCB3ZSd2ZSBsZWFybmVkIHdoaWxlIHdyYW5nbGluZyB0aGUgZmlyc3QgdHdvIHRhYmxlcy4KCmBgYHtyfQpkZjMgPC0gbWFnaWNrOjppbWFnZV9vY3IoaW1hZ2UzKQoKZGYzICU+JQogIGJhc2U6OnN0cnNwbGl0KCJcbiIpICU+JQogIGJhc2U6OnVubGlzdCgpICU+JQogIHRpYmJsZTo6YXNfdGliYmxlKCkKYGBgCgpXZSBhcmUgb2Z0ZW4gcHJlc2VudGVkIHdpdGggc2NlbmFyaW9zIHdoZXJlIHN0YW5kLWFsb25lIGFwcHJvYWNoZXMgYXJlIGRpZmZpY3VsdCBvciB0aW1lLWNvbnN1bWluZy4KCkl0IGlzIGFsd2F5cyBiZXN0IHRvIGRvY3VtZW50IHRoZSBzdGVwcyB0YWtlIHRvIHJlc3BvbmQgdG8gdGhlc2Ugc2NlbmFyaW9zLiBXcmFuZ2xpbmcgdGhpcyB0aGlyZCB0YWJsZSBpcyBhIHByaW1lIGV4YW1wbGUgb2YgdGhpcy4gCgpXZSBhcmUgbWlzc2luZyBhIHJvdy4gTGV0J3MgbWFudWFsbHkgYWRkIHRoZSByb3cuCgpgYGB7cn0KZGYzIDwtIGRmMyAlPiUKICBzdHJzcGxpdCgiXG4iKSAlPiUKICB1bmxpc3QoKSAlPiUKICBhc190aWJibGUoKQoKZGYzIDwtIGRmMyAlPiUKICByYmluZCgiUFIsIERSLCBDdWJhbiAxNS4xIDIxMSwyMDAiKQpgYGAKCldlIGNhbiBub3cgcHJvY2VlZCBhcyB3ZSBkaWQgd2l0aCB0aGUgcHJldmlvdXMgdGFibGVzLiAKCmBgYHtyfQpkZjMgPC0gZGYzICU+JQogIGRwbHlyOjpzZWxlY3QodmFsdWUpICU+JQogIHB1bGwodmFsdWUpICU+JQogIHN0cl9zcGxpdCgiICIpCgpkZjNiIDwtIG1hcChkZjMsIHRhaWwsIDIpICU+JQogIG1hcCh+Z3N1YigiWyxdK3xbLl0rIiwgIiIsLikpICU+JQogIGRvLmNhbGwocmJpbmQsLikgJT4lCiAgZGF0YS5mcmFtZSgpICU+JQogIG11dGF0ZV9pZihpcy5jaGFyYWN0ZXIsIGFzLm51bWVyaWMpICU+JQogIG11dGF0ZV9hdCh2YXJzKC1YMiksIH4gLiAqIDAuMSkgJT4lCiAgdGliYmxlKCkgCgpkZjNhIDwtIGRmMyAlPiUKICBtYXAofnBhc3RlKC4sY29sbGFwc2UgPSAiIikpICU+JQogIG1hcCh+Z3N1YigiW1s6ZGlnaXQ6XV0rfFtbOnB1bmN0Ol1dKyIsICIiLC4pKSAlPiUKICBkby5jYWxsKHJiaW5kLC4pICU+JQogIGRhdGEuZnJhbWUoKSAlPiUKICB0aWJibGUoKQoKcm0oZGYzKQogIApkZjMgPC0gYmluZF9jb2xzKGRmM2EsIGRmM2IpCm5hbWVzKGRmMykgPC0gYygpCgpjb2x1bW5fbmFtZXMgPC0gYygiR3JvdXAiLAogICAgICAgICAgICAgICAgICAiUmF0ZSIsCiAgICAgICAgICAgICAgICAgICJOXzIwMTciKQoKY29sbmFtZXMoZGYzKSA8LSBjb2x1bW5fbmFtZXMKCmBgYAoKSWYgd2UgbG9vayBhdCB0aGUgbGFzdCBmZXcgcm93cywgd2Ugc2VlIHRoYXQgdGhlcmUgaXMgYSB0eXBvLiBUaGVyZSBhcmUgdHdvIGZlbWFsZSBncm91cHMuCgpgYGB7cn0KdGFpbChkZjMpCmBgYAoKU29tZXRpbWVzIHdoZW4gd3JhbmdsaW5nIHRleHQgZGF0YSwgd2Ugd2lsbCBjb21lIGFjcm9zcyBhIHR5cG8uIFdlIG5lZWQgdG8gZGV0ZXJtaW5lIGhvdyB0byByZXNwb25kIHRvIHRoZSB0eXBvIGFuZCBtYWtlIG5vdGUgb2YgaXQuIEl0J3Mgb2Z0ZW4gYmVzdCB0byBjb25zdWx0IGEgc2Vjb25kYXJ5IHNvdXJjZSB0byBjb25maXJtIHRoYXQgY2hhbmdlcyBtYWRlIGFyZSBhY2N1cmF0ZS4gCgpGb3IgdGhlIHB1cnBvc2VzIG9mIHRoaXMgY2FzZSBzdHVkeSwgd2Ugd2lsbCBhc3N1bWUgdGhhdCB0aGUgZmlyc3Qgb2YgdGhlIHR3byByb3dzIHJlcHJlc2VudHMgbWFsZSBkaXNjb25uZWN0aW9uIHJhdGVzIGluIHRoZSBMYXRpbm8vYSBzdWJncm91cDsgdGhpcyB3b3VsZCBiZSBjb25zaXN0ZW50IHdpdGggdGhlIG9yZGVyaW5nIG9mIGdlbmRlcnMgaW4gdGhlIHByZXZpb3VzIHN1Ymdyb3Vwcy4gCgpMZXQncyBtYWtlIHRoZSBjb3JyZWN0aW9uIHRvIHRoZSB0eXBvLgoKYGBge3J9CmRmMyA8LSBkZjMgJT4lCiAgbXV0YXRlKEdyb3VwID0gY2FzZV93aGVuKEdyb3VwID09ICJQUkRSQ3ViYW5GZW1hbGUiICYgTl8yMDE3ID09IDExNDUwMCB+ICJQUkRSQ3ViYW5NYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBHcm91cCkpCmBgYAoKSXQgbG9va3MgbGlrZSB3ZSd2ZSBzdWNjZXNmdWxseSBjb3JyZWN0ZWQgdGhlIHR5cG8uCgpgYGB7cn0KdGFpbChkZjMpCmBgYAoKV2UgY2FuIGNvbnRpbnVlIHdpdGggdGhlIHByb2Nlc3Mgd2UndmUgZGV2ZWxvcGVkIG5vdyB0aGF0IHdlIGhhdmUgbWFkZSB0aGUgY29ycmVjdGlvbi4KCmBgYHtyfQpkZjMgPC0gZGYzICU+JQogIGRwbHlyOjpzZWxlY3QoLU5fMjAxNykKCmRmMyA8LSBkZjMgJT4lCiAgZHBseXI6Om11dGF0ZShZZWFyID0gMjAxNykKCmRmMyA8LSBkZjMgJT4lCiAgbXV0YXRlKEdlbmRlciA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KEdyb3VwLCAiRmVtYWxlIikgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChHcm91cCwgIk1hbGUiKSB+IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BKSwKICAgICAgICAgU3ViZ3JvdXAgPSBzdHJfcmVtb3ZlX2FsbChHcm91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gcGFzdGUoYygiRmVtYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWFsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxBVElOTyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxhdGlubyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxhdGluYSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gInwiKSkpICU+JQogIG11dGF0ZShTdWJncm91cCA9IG5hX2lmKFN1Ymdyb3VwLCAiIikpCgpnbGltcHNlKGRmMykKCmRmMyA8LSBkZjMgJT4lIAogIG11dGF0ZShUeXBlID0gY2FzZV93aGVuKGlzLm5hKEdlbmRlcikgJiBpcy5uYShTdWJncm91cCkgfiAiTGF0aW5vL2EgVG90YWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEdlbmRlcikgJiAhaXMubmEoU3ViZ3JvdXApIH4gIlN1Ymdyb3VwIFRvdGFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEoR2VuZGVyKSAmIGlzLm5hKFN1Ymdyb3VwKSB+ICJHZW5kZXIgVG90YWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiU3ViZ3JvdXAgVG90YWwiKSkKCmdsaW1wc2UoZGYzKQoKZGYzIDwtIGRmMyAlPiUKICBtdXRhdGUoR2VuZGVyID0gY2FzZV93aGVuKHN0cl9kZXRlY3QoR3JvdXAsICJGZW1hbGUiKSB+ICJGZW1hbGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChHcm91cCwgIk1hbGUiKSB+ICJNYWxlIikpCgpkZjMgPC0gZGYzICU+JSAKICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCB0b2xvd2VyKSAlPiUKICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCB0b3VwcGVyKQoKZGYzIDwtIGRmMyAlPiUKICBtdXRhdGUoR2VuZGVyID0gcmVwbGFjZV9uYShHZW5kZXIsICJBTEwiKSwKICAgICAgICAgU3ViZ3JvdXAgPSByZXBsYWNlX25hKFN1Ymdyb3VwLCAiQUxMIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLUdyb3VwKSAlPiUKICBtdXRhdGUoU3ViZ3JvdXApCgpkZjMgPC0gZGYzICU+JQogIG11dGF0ZShTdWJncm91cCA9IGNhc2Vfd2hlbihTdWJncm91cCA9PSAiU09VVEhBTUVSSUNBTiIgfiAiU09VVEggQU1FUklDQU4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdWJncm91cCA9PSAiQ0VOVFJBTEFNRVJJQ0FOIiB+ICJDRU5UUkFMIEFNRVJJQ0FOIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3ViZ3JvdXAgPT0gIlBSRFJDVUJBTiIgfiAiUFIvRFIvQ1VCQU4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gU3ViZ3JvdXApKQpgYGAKCkxldCdzIGFkZCB0aGUgMjAxOCBkYXRhIHRvIHRoaXMgZGF0YWZyYW1lLgoKV2UgaW1wb3J0IHRoZSBpbWFnZS4gCgpgYGB7cn0KaW1hZ2U1IDwtIGltYWdlX3JlYWQoaGVyZSgiaW1nIiwgImxhdGlub19hX3N1Ymdyb3Vwc18yMDE4LnBuZyIpKQoKZGYzXzIwMTggPC0gbWFnaWNrOjppbWFnZV9vY3IoaW1hZ2U1KQpgYGAKCkFzIHlvdSBjYW4gc2VlLCB3ZSBoYXZlIHJlcGVhdGVkIG5ld2xpbmVzIChgXG5gKS4gV2UgY2FuIHJlbW92ZSB0aGVzZSB3aXRoIHNvbWUgc2ltcGxleCByZWdleC4KCmBgYHtyfQpkZjNfMjAxOCA8LSBnc3ViKCcoW1xuXSlcXDErJywKICAgICAgICAgICAgICAgICAnXFwyJywKICAgICAgICAgICAgICAgICBkZjNfMjAxOCkKCmRmM18yMDE4IDwtIGdzdWIoIltbOnB1bmN0Ol1dKyIsCiAgICAgICAgICAgICAgICAgIiIsCiAgICAgICAgICAgICAgICAgZGYzXzIwMTgpCmBgYAoKV2UgcHJvY2VlZCwgbWFraW5nIHNsaWdodCBtb2RpZmljYXRpb25zIHRvIHRoZSBwcm9jZXNzIGFzIG5lZWRlZC4KCmBgYHtyfQpkZjNfMjAxOCA8LSBkZjNfMjAxOCAlPiUKICBzdHJzcGxpdCgiXG4iKSAlPiUKICB1bmxpc3QoKSAlPiUKICBhc190aWJibGUoKQoKZGYzXzIwMTggPC0gZGYzXzIwMTggJT4lCiAgZHBseXI6OnNlbGVjdCh2YWx1ZSkgJT4lCiAgcHVsbCh2YWx1ZSkgJT4lCiAgc3RyX3NwbGl0KCIgIikKCmRmM18yMDE4IDwtIGxhcHBseShkZjNfMjAxOCwKICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHhbbmNoYXIoeCkgPj0gMV0pCgpkZjNhXzIwMTggPC0gZGYzXzIwMTggJT4lCiAgbWFwKH5wYXN0ZSguLGNvbGxhcHNlID0gIiIpKSAlPiUKICBtYXAofmdzdWIoIltbOmRpZ2l0Ol1dK3xbWzpwdW5jdDpdXSsiLCAiIiwuKSkgJT4lCiAgZG8uY2FsbChyYmluZCwuKSAlPiUKICBkYXRhLmZyYW1lKCkgJT4lCiAgdGliYmxlKCkKCmRmM2JfMjAxOCA8LSBtYXAoZGYzXzIwMTgsIHRhaWwsIDIpICU+JQogIGRvLmNhbGwocmJpbmQsLikgJT4lCiAgZGF0YS5mcmFtZSgpICU+JQogIG11dGF0ZV9pZihpcy5jaGFyYWN0ZXIsIGFzLm51bWVyaWMpICU+JQogIG11dGF0ZV9hdCh2YXJzKC1YMiksIH4gLiAqIDAuMSkgJT4lCiAgdGliYmxlKCkgCgpybShkZjNfMjAxOCkKICAKZGYzXzIwMTggPC0gYmluZF9jb2xzKGRmM2FfMjAxOCwKICAgICAgICAgICAgICAgICAgICAgIGRmM2JfMjAxOCkKbmFtZXMoZGYzXzIwMTgpIDwtIGMoKQoKY29sdW1uX25hbWVzIDwtIGMoIkdyb3VwIiwKICAgICAgICAgICAgICAgICAgIlJhdGUiLAogICAgICAgICAgICAgICAgICAiTl8yMDE3IikKCmNvbG5hbWVzKGRmM18yMDE4KSA8LSBjb2x1bW5fbmFtZXMKCmRmM18yMDE4IDwtIGRmM18yMDE4ICU+JQogIGRwbHlyOjpzZWxlY3QoLU5fMjAxNykKCmRmM18yMDE4IDwtIGRmM18yMDE4ICU+JQogIGRwbHlyOjptdXRhdGUoWWVhciA9IDIwMTgpCgpkZjNfMjAxOCA8LSBkZjNfMjAxOCAlPiUKICBtdXRhdGUoR2VuZGVyID0gY2FzZV93aGVuKHN0cl9kZXRlY3QoR3JvdXAsICJXb21lbiIpIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoR3JvdXAsICJNZW4iKSB+IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BKSkKCmxhYmVscyA8LSB1bmxpc3QoZGYzXzIwMThbc2VxKDEsMTIsIGJ5ID0zKSwxXSwgdXNlLm5hbWVzID0gRkFMU0UpCgpkaW0oZGYzXzIwMTgpWzFdCgpsYWJlbHNfMyA8LSByZXAobGFiZWxzLCBlYWNoID0gZGltKGRmM18yMDE4KVsxXS9sZW5ndGgobGFiZWxzKSkKCmRmM18yMDE4JFN1Ymdyb3VwIDwtIGxhYmVsc18zCgpkZjNfMjAxOCA8LSBkZjNfMjAxOCAlPiUgCiAgbXV0YXRlKFR5cGUgPSAiU3ViZ3JvdXAgVG90YWwiKQoKZ2xpbXBzZShkZjNfMjAxOCkKCmRmM18yMDE4IDwtIGRmM18yMDE4ICU+JQogIG11dGF0ZShHZW5kZXIgPSBjYXNlX3doZW4oR2VuZGVyID09IFRSVUUgfiAiRmVtYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdlbmRlciA9PSBGQUxTRSB+ICJNYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiQWxsIikpCgpkZjNfMjAxOCA8LSBkZjNfMjAxOCAlPiUgCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgdG9sb3dlcikgJT4lCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgdG91cHBlcikKCmRmM18yMDE4IDwtIGRmM18yMDE4ICU+JQogIGRwbHlyOjpzZWxlY3QoLUdyb3VwKQoKZGYzXzIwMTggPC0gZGYzXzIwMTggJT4lCiAgbXV0YXRlKFN1Ymdyb3VwID0gY2FzZV93aGVuKFN1Ymdyb3VwID09ICJTT1VUSEFNRVJJQ0FOIiB+ICJTT1VUSCBBTUVSSUNBTiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN1Ymdyb3VwID09ICJDRU5UUkFMQU1FUklDQU4iIH4gIkNFTlRSQUwgQU1FUklDQU4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdWJncm91cCA9PSAiUFJEUkNVQkFOIiB+ICJQUi9EUi9DVUJBTiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBTdWJncm91cCkpCmBgYAoKV2UgbG9hZCB0aGUgUERGLgoKYGBge3J9CnJtKGV4Y2VycHQpCmV4Y2VycHQgPC0gaW1hZ2VfcmVhZChoZXJlKCJpbWciLCAibGF0aW5vX2FfeW91dGhfZXhjZXJwdC5wbmciKSkKCmV4Y2VycHQKYGBgCgpXZSBhZGQgdGhlIHJvd3MuCgpgYGB7cn0KZGYzXzIwMTggPC0gZGYzXzIwMTggJT4lCiAgYWRkX3JvdyhSYXRlID0gMTIuOCwKICAgICAgICAgIFllYXIgPSAyMDE4LAogICAgICAgICAgR2VuZGVyID0gIkFMTCIsCiAgICAgICAgICBTdWJncm91cCA9ICJBTEwiLCAKICAgICAgICAgIFR5cGUgPSAiTEFUSU5PL0EgVE9UQUwiKSAlPiUKICBhZGRfcm93KFJhdGUgPSAxMy4zLAogICAgICAgICAgWWVhciA9IDIwMTgsCiAgICAgICAgICBHZW5kZXIgPSAiRkVNQUxFIiwKICAgICAgICAgIFN1Ymdyb3VwID0gIkFMTCIsIAogICAgICAgICAgVHlwZSA9ICJHRU5ERVIgVE9UQUwiKSAlPiUKICBhZGRfcm93KFJhdGUgPSAxMi4zLAogICAgICAgICAgWWVhciA9IDIwMTgsCiAgICAgICAgICBHZW5kZXIgPSAiTUFMRSIsCiAgICAgICAgICBTdWJncm91cCA9ICJBTEwiLCAKICAgICAgICAgIFR5cGUgPSAiR0VOREVSIFRPVEFMIikKYGBgCgpXZSBhZGQgdGhlIDIwMTggZGF0YSB0byB0aGUgZGF0YWZyYW1lCgpgYGB7cn0KZGYzIDwtIGJpbmRfcm93cyhkZjMsCiAgICAgICAgICAgICAgICAgZGYzXzIwMTgpCmBgYAoKIyMjIE1hcAoKV2Ugd2lsbCB1c2UgbXVsdGlwbGUgaW1hZ2VzIHRvIGltcG9ydCB0aGUgZGF0YSBvbiBwYWdlIDM2IHRvIHByb2R1Y2UgbWFwcy4gCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNmZmNjY2I7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqTUlDSEFFTCBPTlRJVkVST1MqKgoKKlRoaXMgY29kZSBpcyBub3QgY29tcGxldGUuIElmIHRoZXJlIGlzIHRpbWUsIHdlIHdpbGwgcmV0dXJuIHRvIGl0ISBNYWdpY2sgaXMgaGF2aW5nIHRyb3VibGUgd2l0aCBxdWFkcmFudCAxIGFuZCA0LiBJIGNvdWxkIG5vdCBmaWd1cmUgb3V0IHdoeS4qCjwvZGl2PgoKYGBge3IsIGV2YWw9RkFMU0V9CnF1YWRyYW50MSA8LSBpbWFnZV9yZWFkKGhlcmUoImltZyIsICJzdGF0ZV9xdWFkcmFudDEucG5nIikpCnF1YWRyYW50MiA8LSBpbWFnZV9yZWFkKGhlcmUoImltZyIsICJzdGF0ZV9xdWFkcmFudDIucG5nIikpCnF1YWRyYW50MyA8LSBpbWFnZV9yZWFkKGhlcmUoImltZyIsICJzdGF0ZV9xdWFkcmFudDMucG5nIikpCnF1YWRyYW50NCA8LSBpbWFnZV9yZWFkKGhlcmUoImltZyIsICJzdGF0ZV9xdWFkcmFudDQucG5nIikpCgpxdWFkcmFudDEgPC0gbWFnaWNrOjppbWFnZV9vY3IocXVhZHJhbnQxKQpxdWFkcmFudDIgPC0gbWFnaWNrOjppbWFnZV9vY3IocXVhZHJhbnQyKQpxdWFkcmFudDMgPC0gbWFnaWNrOjppbWFnZV9vY3IocXVhZHJhbnQzKQpxdWFkcmFudDQgPC0gbWFnaWNrOjppbWFnZV9vY3IocXVhZHJhbnQ0KQoKbGFiZWxzX3F1YWQxXzMgPC0gcGFzdGUwKHF1YWRyYW50MSwgcXVhZHJhbnQzKQpsYWJlbHNfcXVhZDJfNCA8LSBwYXN0ZTAocXVhZHJhbnQyLCBxdWFkcmFudDQpCgpsYWJlbHNfcXVhZDFfMyA8LSBsYWJlbHNfcXVhZDFfMyAlPiUKICBzdHJzcGxpdCgiXG4iKSAlPiUKICB1bmxpc3QoKSAlPiUKICBhc190aWJibGUoKQoKbGFiZWxzX3F1YWQyXzQgPC0gbGFiZWxzX3F1YWQyXzQgJT4lCiAgc3Ryc3BsaXQoIlxuIikgJT4lCiAgdW5saXN0KCkgJT4lCiAgYXNfdGliYmxlKCkKCmRmMSA8LSBkZjEgJT4lCiAgZHBseXI6OnNlbGVjdCh2YWx1ZSkgJT4lCiAgcHVsbCh2YWx1ZSkgJT4lCiAgc3RyX3NwbGl0KCIgIikKYGBgCgpgYGB7ciwgZXZhbD0gRkFMU0V9CmRhdGFfbWFwIDwtIG1hcF9kYXRhKCJzdGF0ZSIpICU+JQogIGZpbHRlcihyZWdpb249PSJjYWxpZm9ybmlhIikKCnllYXJzIDwtIGMoc2VxKDIwMDgsMjAxNixieT0yKSwyMDE3KQoKaW5kZXhfcmVwIDwtIGRpbShkYXRhX21hcClbMV0KCmRhdGFfbWFwIDwtIGJpbmRfcm93cyhyZXBsaWNhdGUobGVuZ3RoKHllYXJzKSwgZGF0YV9tYXAsIHNpbXBsaWZ5ID0gRkFMU0UpKQoKZGF0YV9tYXAkeWVhciA8LSByZXAoeWVhcnMsIGVhY2ggPSBpbmRleF9yZXApCgpkYXRhX21hcCA8LSBkYXRhX21hcCAlPiUKICBncm91cF9ieShyZWdpb24sIHllYXIpICU+JQogIG11dGF0ZShyYW5rX3JhbiA9IHJhbmsoeWVhciwgdGllcy5tZXRob2QgPSAicmFuZG9tIikpCgpkYXRhX21hcCA8LSBkYXRhX21hcFtvcmRlcihkYXRhX21hcCRvcmRlciksXQoKbGlicmFyeShnZ2FuaW1hdGUpCgpnZ3Bsb3QoZGF0YV9tYXAsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbD1yYW5rX3JhbikpICsKICBnZW9tX3BvbHlnb24oKSArCiAgdHJhbnNpdGlvbl90aW1lKHRpbWUgPSB5ZWFyKQoKYGBgCgojIyAqKkRhdGEgQW5hbHlzaXMqKgoqKiogCgoqKlJlcGVhdGVkIENyb3NzLXNlY3Rpb25hbCBEYXRhKioKCldlIGhhdmUgcG9vbGVkIChyZXBlYXRlZCkgW2Nyb3NzLXNlY3Rpb25hbF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3Mtc2VjdGlvbmFsX2RhdGE/b2xkZm9ybWF0PXRydWUpIGRhdGEuCgpUaGlzIGlzIGRhdGEgcHJvZHVjZWQgZnJvbSByZXBlYXRlZCBtZWFzdXJlbWVudCBvZiBhIFtwb3B1bGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Qb3B1bGF0aW9uP29sZGZvcm1hdD10cnVlKSBvdmVyIHRpbWUuCgpJdCBpcyBvZnRlbiBpbmZlYXNpYmxlIHRvIGNvbGxlY3QgZGF0YSBmb3IgYW4gZW50aXJlIHBvcHVsYXRpb24gYXQgb25jZS4gSG93ZXZlciwgd2UgY2FuIHN0aWxsIG9idGFpbiBtZWFuaW5nZnVsIG1lYXN1cmVzIHVzaW5nIGEgcmFuZG9tIFtzYW1wbGVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXBsaW5nXyhzdGF0aXN0aWNzKT9vbGRmb3JtYXQ9dHJ1ZSkgb2YgdGhlIHBvcHVsYXRpb24uIAoKQXQgc3BlY2lmaWMgdGltZS1wb2ludHMsIGRhdGEgaXMgY29sbGVjdGVkIGZyb20gYSBzYW1wbGUgb2YgdGhlIHBvcHVsYXRpb24uIFRoZSBpbmRpdmlkdWFscyBpbiBlYWNoIHNhbXBsZSBhcmUgbm90IG5lY2Vzc2FyaWx5IHRoZSBzYW1lIGluZGl2aWR1YWxzLiBUaGlzIHNlcGFyYXRlcyBwb29sZWQgY3Jvc3Mtc2VjdGlvbmFsIGRhdGEgZnJvbSBwYW5lbCBkYXRhLCB3aGljaCBpcyBsb25naXR1ZGluYWwgZGF0YSBmcm9tIHJlcGVhdGVkIG1lYXN1cmVtZW50IG9mIHRoZSBzYW1lIHBlb3BsZS4gICAKCkJ5IHNhbXBsaW5nIGZyb20gYSBwb3B1bGF0aW9uIGF0IG11bHRpcGxlIHRpbWUgcG9pbnRzLCB3ZSBjYW4gZ2VuZXJhdGUgcG9wdWxhdGlvbiBsZXZlbCBzdGF0aXN0aWNzLiBBbHRob3VnaCB0aGVzZSBzdGF0aXN0aWNzIGhhdmUgc29tZSByYW5kb20gZXJyb3IsIHRoZXkgY2FuIHByb3ZpZGUgaW5zaWdodCBpbnRvIGhvdyB0aGUgbWVhc3VyZSB2YXJpYWJsZSBpcyBjaGFuZ2luZyBpbiBhIHBvcHVsYXRpb24gb3ZlciB0aW1lLgoKV2UgY2FuIGFjY29tcGxpc2ggdGhpcyBieSBwbG90dGluZyB0aGUgbWVhc3VyZWQgdmFsdWVzIG92ZXIgdGltZS4gU29tZXRpbWVzLCBob3dldmVyLCB0aGUgdHJlbmQgaXNuJ3QgZXhhY3RseSBjbGVhci4gRm9ydHVuYXRlbHksIHRoZXJlIGFyZSBzdGF0aXN0aWNhbCBtZXRob2RzIHRvIHJlc29sdmUgdGhpcyBpc3N1ZS4KClRoZSBNYW5uLUtlbmRhbGwgdHJlbmQgdGVzdOKAlGEgdmFyaWF0aW9uIG9mIHRoZSBbS2VuZGFsbCByYW5rIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9LZW5kYWxsX3JhbmtfY29ycmVsYXRpb25fY29lZmZpY2llbnQ/b2xkZm9ybWF0PXRydWUp4oCUdGVzdHMgd2hldGhlciB0aGVyZSBpcyBhIG1vbm90b25pYyBhc3NvY2lhdGlvbiwgYW4gYXNzb2NpYXRpb24gdGhhdCBkb2VzIG5vdCBpbmNyZWFzZSBvciBkZWNyZWFzZSBidXQgcmVtYWlucyBzdGF0aWMgYWNyb3NzIGEgZGltZW5zaW9uLgoKUmVjYWxsIHRoZSB5b3V0aCBkaXNjb25uZWN0aW9uIHJhdGVzIGZvciBOYXRpdmUgQW1lcmljYW5zLCBzb21lIG9mIHRoZSBoaWdoZXN0IGluIHRoZSBmaXJzdCB0YWJsZSB3ZSBleGFtaW5lZC4gCgpgYGB7cn0KaW1hZ2VfZXhhbXBsZQpgYGAKCkxldCdzIGNvbmR1Y3QgYSBNYW5uLUtlbmRhbGwgdGVzdCBmb3IgdHJlbmQuCgpXZSBjYW4gYWNjb21wbGlzaCB0aGlzIHdpdGggdGhlIGBLZW5kYWxsOjpNYW5uS2VuZGFsbCgpYCBmdW5jdGlvbi4gVGhlIGBLZW5kYWxsOjpNYW5uS2VuZGFsbCgpYCBhY2NlcHRzIGEgdmVjdG9yIG9mIGRhdGEgZm9yIHdoaWNoIGEgdHJlbmQgbWF5IGJlIG9ic2VydmVkLiBbQ29uc3VsdGluZyB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgdGhlIGBLZW5kYWxsOjpNYW5uS2VuZGFsbCgpYCBmdW5jdGlvbiBhdmFpbGFibGUgb24gQ1JBTl0oaHR0cHM6Ly9yZHJyLmlvL2NyYW4vS2VuZGFsbC9tYW4vTWFubktlbmRhbGwuaHRtbCksIHdlIGNhbiAidGVzdCBmb3IgYSBhIG1vbm90b25pYyB0cmVuZCBpbiBhIHRpbWUgc2VyaWVzIi4KCmBgYHtyfQpkZjEgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAiQUxMIiwKICAgICAgICAgUmFjZSA9PSAiTkFUSVZFIEFNRVJJQ0FOIikgJT4lCiAgcHVsbChSYXRlKSAlPiUKICBNYW5uS2VuZGFsbCguKSAlPiUKICBzdW1tYXJ5KCkKYGBgCgpUaGVyZSBkb2VzIG5vdCBhcHBlYXIgdG8gYmUgYSBjaGFuZ2UgaW4gdGhlIHRyZW5kLiBIb3dldmVyLCBpdCdzIGltcG9ydGFudCB0byBub3RlIHRoYXQgd2Ugb25seSBoYXZlIGByIGxlbmd0aChkZjEgJT4lIGZpbHRlcihHZW5kZXIgPT0gIkFMTCIsIFJhY2UgPT0gIk5BVElWRSBBTUVSSUNBTiIpICU+JSBwdWxsKFJhdGUpKWAgb2JzZXJ2YXRpb25zLgoKV2UgY2FuIGFsc28gZXhwbG9yZSB0aGUgdHJlbmQgdXNpbmcgW3NpbXBsZSBsaW5lYXIgcmVncmVzc2lvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2ltcGxlX2xpbmVhcl9yZWdyZXNzaW9uP29sZGZvcm1hdD10cnVlKS4gCgpgYGB7cn0KZGYxICU+JQogIGZpbHRlcihHZW5kZXIgPT0gIkFMTCIsCiAgICAgICAgIFJhY2UgPT0gIk5BVElWRSBBTUVSSUNBTiIpICU+JQogIGxtKFJhdGUgfiBZZWFyLCBkYXRhID0gLikgJT4lCiAgc3VtbWFyeSgpCmBgYAoKRm9yIGVhY2ggb25lIHllYXIgY2hhbmdlLCB0aGUgbWVhbiBpbmNyZWFzZSBpbiBkaXNjb25uZWN0aW9uIHJhdGVzIGlzIGByIChkZjEgJT4lIGZpbHRlcihHZW5kZXIgPT0gIkFMTCIsIFJhY2UgPT0gIk5BVElWRSBBTUVSSUNBTiIpICU+JSBsbShSYXRlIH4gWWVhciwgZGF0YSA9IC4pKVtbImNvZWZmaWNpZW50cyJdXVsiWWVhciJdYC4gVGhpcyByZWxhdGlvbnNoaXAgaXMgbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIEFnYWluLCB3ZSBhcmUgbGFyZ2VseSBsaW1pdGVkIGJ5IHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGluIHRoaXMgZGF0YXNldC4gCgpXZSBjYW4gdmlzdWFsaXplIHRoZSByZWxhdGlvbnNoaXAgYWJvdmUuCgpgYGB7cn0KZGYxICU+JQogIGZpbHRlcihHZW5kZXIgPT0gIkFMTCIsCiAgICAgICAgIFJhY2UgPT0gIk5BVElWRSBBTUVSSUNBTiIpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBSYXRlKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gInJlZCIpICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA4LCAyMDE4LCBieSA9IDEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwOCwgMjAxOCwgYnkgPSAxKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA4LCAyMDE4KSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJZb3V0aCBEaXNjb25uZWN0aW9uIFJhdGVzIG9mIE5hdGl2ZSBBbWVyaWNhbiBZb3V0aCIsCiAgICAgICBzdWJ0aXRsZSA9ICIyMDA4IC0gMjAxNyIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJEaXNjb25uZWN0aW9uIFJhdGUiKQpgYGAKCkFzIHdlIGNhbiBzZWUsIHRoZXJlIGlzIGEgbGFyZ2UgYW1vdW50IG9mIHVuY2VydGFpbnR5IGFyb3VuZCB0aGUgZml0dGVkIGxpbmUuIAoKTGV0J3MgdmlzdWFsaXplIHRoZSBkYXRhISAKCiMjICoqRGF0YSBWaXN1YWxpemF0aW9uKioKKioqIAoKTGV0J3MgcmVwcm9kdWNlIHRoZSBleGFtcGxlIGJlbG93LgoKYGBge3IsIG91dC53aWR0aCA9ICIxMDAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJNYWtpbmdfdGhlX0Nvbm5lY3Rpb25fcGxvdC5wbmciKSkKYGBgCgpXZSBjYW4gY3JlYXRlIGEgdmVyc2lvbiBvZiB0aGUgYWJvdmUgZXhhbXBsZSB3aXRoIGBnZ3Bsb3RgIGZyb20gYHRpZHl2ZXJzZWAuCgpUaGVyZSBhcmUgY29sb3IgaWRlbnRpZnlpbmcgd2Vic2l0ZXMgb25seSBzdWNoIGFzIFt0aGlzXShodHRwczovL2ltYWdlY29sb3JwaWNrZXIuY29tL2VuLykuCgpVc2luZyBvbmUgb2YgdGhlc2Ugd2Vic2l0ZXMsIHdlIGlkZW50aWZ5IHRoZSBbaGV4IHRyaXBsZXRdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9jb2xvcnM/b2xkZm9ybWF0PXRydWUpIGZvciB0aGUgY29sb3IgdXNlZCBpbiB0aGUgdmlzdWFsaXphdGlvbiBpbmNsdWRlZCBpbiB0aGUgUERGOiBgIzAwODM5M2AuIAoKYGBge3J9CmZhX2ZpZ3VyaW5lIDwtIGltYWdlX3JlYWQoImh0dHBzOi8vdXBsb2FkLndpa2ltZWRpYS5vcmcvd2lraXBlZGlhL2NvbW1vbnMvNy83Yy9Vc2VyX2ZvbnRfYXdlc29tZS5zdmciKQoKZmFfZmlndXJpbmUgPC0gaW1hZ2VfZmlsbChmYV9maWd1cmluZSwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjMDA4MzkzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnQgPSAiKzgwMCs4MDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGZ1enogPSAwKQoKZmFfZmlndXJpbmUgPC0gaW1hZ2VfZmlsbChmYV9maWd1cmluZSwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjMDA4MzkzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnQgPSAiKzgwMCsxMDAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBmdXp6ID0gMCkKCmRmMSAlPiUKICBmaWx0ZXIoVHlwZSA9PSAiUkFDRSBUT1RBTCIpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBSYXRlLCBncm91cD1SYWNlKSkgKwogIGdlb21fbGluZShjb2xvciA9ICIjMDA4MzkzIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fcG9pbnQoY29sb3IgPSAiIzAwODM5MyIsIHNpemUgPSAzKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA4LDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDgsMjAxOCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDUsMzAsIGJ5ID01KSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYyg1LDMwKSkgKwogIGRyYXdfaW1hZ2UoZmFfZmlndXJpbmUsIHggPSAyMDE3LCB5ID0gMjMuNSwgc2NhbGUgPSAyKSArCiAgZHJhd19pbWFnZShmYV9maWd1cmluZSwgeCA9IDIwMTcsIHkgPSAxNy41LCBzY2FsZSA9IDIpICsKICBkcmF3X2ltYWdlKGZhX2ZpZ3VyaW5lLCB4ID0gMjAxNywgeSA9IDEzLCBzY2FsZSA9IDIpICsKICBkcmF3X2ltYWdlKGZhX2ZpZ3VyaW5lLCB4ID0gMjAxNywgeSA9IDksIHNjYWxlID0gMikgKwogIGRyYXdfaW1hZ2UoZmFfZmlndXJpbmUsIHggPSAyMDE3LCB5ID0gNi41LCBzY2FsZSA9IDIpICsKICBsYWJzKHRpdGxlID0gIkZJR1VSRSAxIFlPVVRIIERJU0NPTk5FQ1RJT04gQlkgUkFDRSBBTkQgRVRITklDSVRZLCAyMDA4IC0gMjAxNyIsCiAgICAgICB5ID0gIllPVVRIIERJU0NPTk5FQ1RJT04gKCUpIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMwMDgzOTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgpXZSBjYW4gYnVpbGQgb2ZmIG9mIHRoaXMgaWRlYSwgdXNpbmcgYSBjdXN0b20gY29sb3IgcGFsZXR0ZSB0byBjcmVhdGUgYSBncmFkaWVudCBiYXNlZCBvZmYgdGhlIGNvbG9yIHVzZWQuIAoKYGBge3J9CmN1c3RvbV9wYWwgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICIjMDA4MzkzIikpCmdlbmRlcl9uIDwtIDMKCmFzaWFuX3RvdGFsIDwtIGRmMiAlPiUKICBmaWx0ZXIoWWVhciA9PSAyMDE3KSAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJBTEwiLAogICAgICAgICBTdWJncm91cCA9PSAiQUxMIikgJT4lCiAgcHVsbChSYXRlKQoKZGYyICU+JQogIGZpbHRlcihZZWFyID09IDIwMTcpICU+JQogIGNvbXBsZXRlKEdlbmRlciwgU3ViZ3JvdXApICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgbXV0YXRlKHN1Yl9yYW5rID0gcmFuayhSYXRlLCB0aWVzLm1ldGhvZCA9ICJtaW4iKSkgJT4lCiAgZ3JvdXBfYnkoU3ViZ3JvdXApICU+JQogIG11dGF0ZShyYW5rX2FsbCA9IHN1Yl9yYW5rW0dlbmRlciA9PSAiQUxMIl0pICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoU3ViZ3JvdXAgPSBmY3RfcmVvcmRlcihTdWJncm91cCwgcmFua19hbGwpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBTdWJncm91cCwgeSA9IFJhdGUsIGZpbGwgPSBHZW5kZXIpKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gYXNpYW5fdG90YWwsIAogICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgbGluZXR5cGUgPSAyKSArIAogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLAogICAgICAgICAgIGNvbG9yID0gInRyYW5zcGFyZW50IiwKICAgICAgICAgICBzaXplID0gMC41LAogICAgICAgICAgIHBvc2l0aW9uID0gImRvZGdlIiwKICAgICAgICAgICB3aWR0aCA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiRklHVVJFIFggWU9VVEggRElTQ09OTkVDVElPTiBCWSBBU0lBTiBTVUJHUk9VUCwgMjAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJPUkRFUkVEIEJZIE9WRVJBTEwgRElTQ09OTkVDVElPTiIsCiAgICAgICB5ID0gIllPVVRIIERJU0NPTk5FQ1RJT04gKCUpIiwKICAgICAgIGZpbGwgPSAiR2VuZGVyIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHJldihjdXN0b21fcGFsKGdlbmRlcl9uICsgMSkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDIwLDIpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMCwyMCwyKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDIwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMwMDgzOTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKSArCiAgYW5ub3RhdGUoInRleHQiLCBsYWJlbCA9ICdib2xkKCJBU0lBTiBUT1RBTCIpJywKICAgICAgICAgICBjb2xvciA9ICIjMDA4MzkzIiwgCiAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgeCA9IDEuMiwKICAgICAgICAgICB5ID0gYXNpYW5fdG90YWwgKyAxLAogICAgICAgICAgIHBhcnNlID0gVFJVRSkKYGBgCgpGcm9tIHRoZSBhYm92ZSBwbG90LCBpdCBiZWNvbWVzIGFwcGFyZW50IHRoYXQgdGhlIEhtb25nIHN1Ymdyb3VwIHByb2R1Y2VzIGEgc21hbGwgcHJvcG9ydGlvbiBvZiB0aGUgdG90YWwgbnVtYmVyIG9mIGFzaWFuIGRpc2Nvbm5lY3RlZCB5b3V0aC4gVGhlIEFzaWFuIHRvdGFsIHlvdXRoIGRpc2Nvbm5lY3Rpb24gcmF0ZSBpcyBtb3JlIGFsaWtlIHRoZSB5b3V0aCBkaXNjb25uZWN0aW9uIHJhdGVzIGZvciBhbGwgb3RoZXIgc3ViZ3JvdXBzIHRoYW4gdGhlIEhtb25nIHlvdXRoIGRpc2Nvbm5lY3Rpb24gcmF0ZS4KCldlIGNhbiBjb25maXJtIHRoaXMgYnkgcmV2aXNpdGluZyB0aGUgdGFibGUuCgpgYGB7cn0KaW1hZ2UyCmBgYAoKVGhlIEhtb25nIGdyb3VwIHJlcHJlc2VudHMgYHIgcm91bmQoKDgzMDAqMTAwKS8xNDU2MDApYCUgb2YgYWxsIEFzaWFuIGRpc2Nvbm5lY3RlZCB5b3V0aC4gCgpUaGlzIHNob3dzIHRoZSBpbXBvcnRhbmNlIG9mIGFkZGluZyBzbWFsbCBkZXRhaWxzIHN1Y2ggYXMgdGhlIGNvbXBvc2l0ZSBsaW5lIHRvIHBsb3RzLiBJdCBoZWxwcyBwcm92aWRlIGEgc2ltcGxlIHlldCBudWFuY2VkIHBpY3R1cmUgb2Ygd2hhdCBpcyBnb2luZyBvbi4gCgpMYXN0bHksIHdlIGNhbiBhZGQgYW5ub3RhdGlvbnMgdG8gYWRkIHByb3ZpZGUgZXZlbiBtb3JlIGRlcHRoIHRvIHRoZSB2aXN1YWxpemF0aW9uLiAKCmBgYHtyfQpsYXRpbm9fYV90b3RhbCA8LSBkZjMgJT4lCiAgZmlsdGVyKFllYXIgPT0gMjAxNykgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAiQUxMIiwKICAgICAgICAgU3ViZ3JvdXAgPT0gIkFMTCIpICU+JQogIHB1bGwoUmF0ZSkKCmRmMyAlPiUKICBmaWx0ZXIoWWVhciA9PSAyMDE3KSAlPiUKICBjb21wbGV0ZShHZW5kZXIsIFN1Ymdyb3VwKSAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIG11dGF0ZShzdWJfcmFuayA9IHJhbmsoUmF0ZSwgdGllcy5tZXRob2QgPSAibWluIikpICU+JQogIGdyb3VwX2J5KFN1Ymdyb3VwKSAlPiUKICBtdXRhdGUocmFua19hbGwgPSBzdWJfcmFua1tHZW5kZXIgPT0gIkFMTCJdKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKFN1Ymdyb3VwID0gZmN0X3Jlb3JkZXIoU3ViZ3JvdXAsIHJhbmtfYWxsKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gU3ViZ3JvdXAsIHkgPSBSYXRlLCBmaWxsID0gR2VuZGVyKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGxhdGlub19hX3RvdGFsLCAKICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgICAgIGxpbmV0eXBlID0gMikgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBjb2xvciA9ICJ0cmFuc3BhcmVudCIsCiAgICAgICAgICAgc2l6ZSA9IDAuNSwKICAgICAgICAgICBwb3NpdGlvbiA9ICJkb2RnZSIsCiAgICAgICAgICAgd2lkdGggPSAwLjUpICsKICBsYWJzKHRpdGxlID0gIkZJR1VSRSBYIFlPVVRIIERJU0NPTk5FQ1RJT04gQlkgTEFUSU5PL0EgU1VCR1JPVVAsIDIwMTciLAogICAgICAgc3VidGl0bGUgPSAiT1JERVJFRCBCWSBPVkVSQUxMIERJU0NPTk5FQ1RJT04iLAogICAgICAgeSA9ICJZT1VUSCBESVNDT05ORUNUSU9OICglKSIsCiAgICAgICBmaWxsID0gIkdlbmRlciIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSByZXYoY3VzdG9tX3BhbChnZW5kZXJfbiArIDEpKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwyMCwyKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDAsMjAsMiksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwyMCkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjMDA4MzkzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgbGFiZWwgPSAnYm9sZCgiTEFUSU5PIFRPVEFMIiknLAogICAgICAgICAgIGNvbG9yID0gIiMwMDgzOTMiLCAKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICB4ID0gMS4yLAogICAgICAgICAgIHkgPSBsYXRpbm9fYV90b3RhbCArIDEsCiAgICAgICAgICAgcGFyc2UgPSBUUlVFKQpgYGAKCmBgYHtyfQpkZjIgJT4lCiAgY29tcGxldGUoR2VuZGVyLCBTdWJncm91cCwgWWVhcikgJT4lCiAgZ3JvdXBfYnkoU3ViZ3JvdXApICU+JQogIG11dGF0ZShtaXNzaW5nID0gc3VtKGlzLm5hKFJhdGUpKSkgJT4lCiAgZmlsdGVyKG1pc3NpbmcgPT0gMCkgJT4lCiAgZHBseXI6OnNlbGVjdCgtbWlzc2luZykgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgbXV0YXRlKHN1Yl9yYW5rID0gcmFuayhSYXRlLCB0aWVzLm1ldGhvZCA9ICJtaW4iKSkgJT4lCiAgZ3JvdXBfYnkoU3ViZ3JvdXAsIFllYXIpICU+JQogIG11dGF0ZShyYW5rX2FsbCA9IHN1Yl9yYW5rW0dlbmRlciA9PSAiQUxMIl0pICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShZZWFyKSAlPiUKICBtdXRhdGUodGhyZXNob2xkID0gUmF0ZVtHZW5kZXIgPT0gIkFMTCIgJiBTdWJncm91cCA9PSAiQUxMIl0pICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoU3ViZ3JvdXAgPSBmY3RfcmVvcmRlcihTdWJncm91cCwgcmFua19hbGwpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBTdWJncm91cCwgeSA9IFJhdGUsIGZpbGwgPSBHZW5kZXIpKSArCiAgZmFjZXRfd3JhcChZZWFyIH4uLCBuY29sID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSB0aHJlc2hvbGQpLCBsaW5ldHlwZSA9IDIpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBjb2xvciA9ICJ0cmFuc3BhcmVudCIsCiAgICAgICAgICAgc2l6ZSA9IDAuNSwKICAgICAgICAgICBwb3NpdGlvbiA9ICJkb2RnZSIsCiAgICAgICAgICAgd2lkdGggPSAwLjUpICsKICBsYWJzKHRpdGxlID0gIkZJR1VSRSBYIFlPVVRIIERJU0NPTk5FQ1RJT04gQlkgQVNJQU4gU1VCR1JPVVAsIDIwMTctMjAxOCIsCiAgICAgICBzdWJ0aXRsZSA9ICJPUkRFUkVEIEJZIE9WRVJBTEwgRElTQ09OTkVDVElPTiIsCiAgICAgICB5ID0gIllPVVRIIERJU0NPTk5FQ1RJT04gKCUpIiwKICAgICAgIGZpbGwgPSAiR2VuZGVyIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHJldihjdXN0b21fcGFsKGdlbmRlcl9uICsgMSkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEwLDIpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMCwxMCwyKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDEwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMwMDgzOTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKQpgYGAKCmBgYHtyfQpkZjMgJT4lCiAgY29tcGxldGUoR2VuZGVyLCBTdWJncm91cCwgWWVhcikgJT4lCiAgZ3JvdXBfYnkoU3ViZ3JvdXApICU+JQogIG11dGF0ZShtaXNzaW5nID0gc3VtKGlzLm5hKFJhdGUpKSkgJT4lCiAgZmlsdGVyKG1pc3NpbmcgPT0gMCkgJT4lCiAgZHBseXI6OnNlbGVjdCgtbWlzc2luZykgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgbXV0YXRlKHN1Yl9yYW5rID0gcmFuayhSYXRlLCB0aWVzLm1ldGhvZCA9ICJtaW4iKSkgJT4lCiAgZ3JvdXBfYnkoU3ViZ3JvdXAsIFllYXIpICU+JQogIG11dGF0ZShyYW5rX2FsbCA9IHN1Yl9yYW5rW0dlbmRlciA9PSAiQUxMIl0pICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShZZWFyKSAlPiUKICBtdXRhdGUodGhyZXNob2xkID0gUmF0ZVtHZW5kZXIgPT0gIkFMTCIgJiBTdWJncm91cCA9PSAiQUxMIl0pICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoU3ViZ3JvdXAgPSBmY3RfcmVvcmRlcihTdWJncm91cCwgcmFua19hbGwpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBTdWJncm91cCwgeSA9IFJhdGUsIGZpbGwgPSBHZW5kZXIpKSArCiAgZmFjZXRfd3JhcChZZWFyIH4uLCBuY29sID0gMSkgKwogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSB0aHJlc2hvbGQpLCBsaW5ldHlwZSA9IDIpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBjb2xvciA9ICJ0cmFuc3BhcmVudCIsCiAgICAgICAgICAgc2l6ZSA9IDAuNSwKICAgICAgICAgICBwb3NpdGlvbiA9ICJkb2RnZSIsCiAgICAgICAgICAgd2lkdGggPSAwLjUpICsKICBsYWJzKHRpdGxlID0gIkZJR1VSRSBYIFlPVVRIIERJU0NPTk5FQ1RJT04gQlkgTEFUSU5PL0EgU1VCR1JPVVAsIDIwMTciLAogICAgICAgc3VidGl0bGUgPSAiT1JERVJFRCBCWSBPVkVSQUxMIERJU0NPTk5FQ1RJT04iLAogICAgICAgeSA9ICJZT1VUSCBESVNDT05ORUNUSU9OICglKSIsCiAgICAgICBmaWxsID0gIkdlbmRlciIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSByZXYoY3VzdG9tX3BhbChnZW5kZXJfbiArIDEpKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwyMCwyKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDAsMjAsMiksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwyMCkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjMDA4MzkzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkKYGBgCgojIyAqKlN1bW1hcnkqKgoqKiogCgojIyAqKlN1Z2dlc3RlZCBIb21ld29yayoqCioqKiAKCjEpIEZpbmQgYW5vdGhlciB0YWJsZSBpbiB0aGUgZG9jdW1lbnQuIEZpbmQgZGlmZmVyZW5jZXMgYmV0d2VlbiBncm91cHMgd2l0aCB0aGUgcHJvY2VzcyBkZXNjcmliZWQgYWJvdmUuIAoKIyMgKipIZWxwZnVsIExpbmtzKioKKioqIAoKCmF2b2NhZG8qVGhpcyBjb25jZXB0cyBsaXN0ZWQgaGVyZSBtdXN0IGJlIHJldmlzaXRlZC4qCgoKPHU+VGVybXMgYW5kIGNvbmNlcHRzIGNvdmVyZWQ6PC91PiAgCgpbVGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltSU3R1ZGlvIGNoZWF0c2hlZXRzXShodHRwczovL3JzdHVkaW8uY29tL3Jlc291cmNlcy9jaGVhdHNoZWV0cy8pe3RhcmdldD0iX2JsYW5rIn0gIApbSW5mZXJlbmNlXShodHRwczovL3d3dy5icml0YW5uaWNhLmNvbS9zY2llbmNlL2luZmVyZW5jZS1zdGF0aXN0aWNzKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1JlZ3Jlc3Npb25dKGh0dHBzOi8vbGluZGVsb2V2LmdpdGh1Yi5pby90ZXN0cy1hcy1saW5lYXIvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0RpZmZlcmVudCB0eXBlcyBvZiByZWdyZXNzaW9uXShodHRwczovL3d3dy5hbmFseXRpY3N2aWRoeWEuY29tL2Jsb2cvMjAxNS8wOC9jb21wcmVoZW5zaXZlLWd1aWRlLXJlZ3Jlc3Npb24vKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW09yZGluYXJ5IGxlYXN0IHNxdWFyZXMgbWV0aG9kXShodHRwOi8vc2V0b3NhLmlvL2V2L29yZGluYXJ5LWxlYXN0LXNxdWFyZXMtcmVncmVzc2lvbi8pe3RhcmdldD0iX2JsYW5rIn0gIApbUmVzaWR1YWxdKGh0dHBzOi8vd3d3LnN0YXRpc3RpY3Nob3d0by5kYXRhc2NpZW5jZWNlbnRyYWwuY29tL3Jlc2lkdWFsLyl7dGFyZ2V0PSJfYmxhbmsifSAgCgo8dT5QYWNrYWdlcyB1c2VkIGluIHRoaXMgY2FzZSBzdHVkeTogPC91PgoKIFBhY2thZ2UgICB8IFVzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbKipoZXJlKipdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEKWyoqdGlkeXZlcnNlKipdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IGZvciBkYXRhIHNjaWVuY2Ugb3BlcmF0aW9ucwpbKipwZGZ0b29scyoqXShodHRwczovL3JlYWRyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBtYW5hZ2UgUERGIGRvY3VtZW50cwpbKiptYWdpY2sqKl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ2ljay92aWduZXR0ZXMvaW50cm8uaHRtbCNLZXJuZWxfY29udm9sdXRpb24pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IGZvciBpbWFnZSBwcm9jZXNzaW5nIAoKIyMgQWNrbm93bGVkZ2VtZW50cwoKV2Ugd291bGQgbGlrZSB0byBhY2tub3dsZWRnZSBbVGFtYXIgTWVuZGVsc29uXShodHRwczovL3d3dy5qaHNwaC5lZHUvZmFjdWx0eS9kaXJlY3RvcnkvcHJvZmlsZS8xNzcwL3RhbWFyLW1lbmRlbHNvbikgZm9yIGFzc2lzdGluZyBpbiBmcmFtaW5nIHRoZSBtYWpvciBkaXJlY3Rpb24gb2YgdGhlIGNhc2Ugc3R1ZHkuCgpXZSB3b3VsZCBhbHNvIGxpa2UgdG8gYWNrbm93bGVkZ2UgdGhlIFtCbG9vbWJlcmcgQW1lcmljYW4gSGVhbHRoIEluaXRpYXRpdmVdKGh0dHBzOi8vYW1lcmljYW5oZWFsdGguamh1LmVkdS8pIGZvciBmdW5kaW5nIHRoaXMgd29yay4g